2

This is an example using classloader and you can see the output. Why are obj's and obj2's classloaders different? I know about the 'delegate to parent classloader' idea.

public class jvm_77{

    public static void main(String[] args) throws Exception{
        ClassLoader myLoader = new ClassLoader(){

            public Class<?> loadClass(String name) throws ClassNotFoundException{
                try
                {
                    String fileName = name.substring(name.lastIndexOf(".")+1)+".class";
                    InputStream is = getClass().getResourceAsStream(fileName);
                    if(is == null)
                    {
                        return super.loadClass(name);
                    }
                    byte[] b = new byte[is.available()];
                    is.read(b);
                    return defineClass(name,b,0,b.length);
                }catch(IOException e)
                {
                    throw new ClassNotFoundException(name);
                }
            }

        };

        Object obj = myLoader.loadClass("Chapter7_ClassLoader.jvm_77").newInstance();
        jvm_77 obj2 = new jvm_77();

        System.out.println(obj.getClass().getClassLoader()); //Chapter7_ClassLoader.jvm_77$1@1888759
        System.out.println(obj2.getClass().getClassLoader()); //sun.misc.Launcher$AppClassLoader@45a877

        System.out.println(obj.equals(obj2));//false
        System.out.println(obj instanceof Chapter7_ClassLoader.jvm_77);//false
        System.out.println(obj2 instanceof Chapter7_ClassLoader.jvm_77);//true
    }

}
John Kugelman
  • 349,597
  • 67
  • 533
  • 578

1 Answers1

2

Why obj's classloader and obj2's classloader are different?

This line is creating an instance of the jvm_77 class that was loaded by the standard classloader.

jvm_77 obj2 = new jvm_77();

This line is creating an instance of the jvm_77 class that was located by your custom classloader.

Object obj = myLoader.loadClass("Chapter7_ClassLoader.jvm_77").newInstance();

So basically, what you are asking is why the two approaches don't give you the same Class object. And the answer to that is in the way that you have implemented loadClass in you classloader:

  • The default behaviour for a loadClass method is:

    1. Try the parent classloader
    2. If that fails, check if we've already loaded the class
    3. If that fails, find the resource and load the class.
  • Your classloader's loadClass method does this:

    1. Attempt to find resource
    2. If the resource find succeeds, load the resource
    3. If the resource find fails, try the parent classloader.

Clearly, your custom classloader is going to attempt to define a new class ... if possible. And apparently, it is succeeding.


In short, the classloaders are different in the output because of the way you implemented the loadClass method.

Stephen C
  • 698,415
  • 94
  • 811
  • 1,216