Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Loading a class twice in JVM using different loaders

I have one question regarding concepts of class loading. How to load a .class file twice in JVM. I am also writing an excerpt of code that I have written to accomplish this..

1) Loader 1 code

public class MyClassLoader extends ClassLoader {

    public MyClassLoader(){
        super(MyClassLoader.class.getClassLoader());
    }

    public Class loadClass(String classname){
        try {
            return super.loadClass(classname);
        } catch (ClassNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return null;
    }
}

2) Loader 2 code

public class AnotherClassLoader extends ClassLoader {

    public AnotherClassLoader(){
        super(AnotherClassLoader.class.getClassLoader());
    }

    public Class loadClass(String classname){
        try {
            return super.loadClass(classname);
        } catch (ClassNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return null;
    }
}

3) Now i am loading a class named A using this two different class loaders. I suppose the operation classA1==newClassA should return false. Here is the code:

public static void main(String[] args) {
        MyClassLoader loader1 = new MyClassLoader();
        AnotherClassLoader newLoader = new AnotherClassLoader();
            System.out.println("Load with Custom Class Loader instance");
            Class classA1 = loader1.loadClass("com.hitesh.coreJava.A");
            System.out.println("Class Loader:::"+classA1.getClassLoader());
            Class newClassA = newLoader.loadClass("com.hitesh.coreJava.A");
            System.out.println("Class Loader:::"+newClassA.getClassLoader());
            System.out.println(classA1==newClassA);
            System.out.println(classA1.hashCode() + " , " + newClassA.hashCode());

    }

4) Result of executing above code:

Load with Custom Class Loader instance Class Loader:::sun.misc.Launcher$AppClassLoader@11b86e7 Class Loader:::sun.misc.Launcher$AppClassLoader@11b86e7 true 1641745 , 1641745

Could you please explain this

like image 858
Hitesh Avatar asked Jan 10 '13 11:01

Hitesh


2 Answers

Try this

public class Test1 {

    static class TestClassLoader1 extends ClassLoader {

        @Override
        public Class<?> loadClass(String name) throws ClassNotFoundException {
            if (!name.equals("Test1")) {
                return super.loadClass(name);
            }
            try {
                InputStream in = ClassLoader.getSystemResourceAsStream("Test1.class");
                byte[] a = new byte[10000];
                int len  = in.read(a);
                in.close();
                return defineClass(name, a, 0, len);
            } catch (IOException e) {
                throw new ClassNotFoundException();
            }
        }
    }


    public static void main(String[] args) throws Exception {
        Class<?> c1 = new TestClassLoader1().loadClass("Test1");
        Class<?> c2 = new TestClassLoader1().loadClass("Test1");
        System.out.println(c1);
        System.out.println(c2);
        System.out.println(c1 == c2);
    }
}

output

class Test1
class Test1
false
like image 56
Evgeniy Dorofeev Avatar answered Sep 22 '22 12:09

Evgeniy Dorofeev


Both classloaders start the lookup in their parent classloader (that's what the super() call is about). So actually the super classloader loads it in both cases.

You can try this:

String pathToJar = "C:\\path\\to\\my.jar";
String className = "com.mypackage.ClassA";
URLClassLoader cl1 = new URLClassLoader(new URL[] { new URL(pathToJar) });
URLClassLoader cl2 = new URLClassLoader(new URL[] { new URL(pathToJar) });
Class<?> c1 = cl1.loadClass(className);
Class<?> c2 = cl2.loadClass(className);
System.out.println(c1);
System.out.println(c2);
System.out.println(c1==c2 ? "Parent classloader loads" : "Parent classloader does not load");
cl1.close();
cl2.close();

Make sure that my.jar is NOT on your classpath.

like image 20
gaborsch Avatar answered Sep 22 '22 12:09

gaborsch