自定義ClassLoader測試

參考博客:
深入分析ClassLoader

在閱讀文章後,對例子進行更詳細的解析。

  1. Parend接口
public interface Parent {
    public void say();
}
  1. Man實現類
public class Man implements Parent {
    @Override
    public void say() {
        System.out.println("hi, I'm a boy!");
    }
}
  1. MyClassLoader類
public class MyClassLoader extends ClassLoader {

    @Override
    protected Class<?> findClass(String name) throws ClassNotFoundException {
        System.out.println("my class loader find class");
        byte[] bt = loadClassData(name);
        return defineClass(name, bt, 0, bt.length);
    }

    private byte[] loadClassData(String className) {
        InputStream is = getClass().getClassLoader().getResourceAsStream(className.replace(".", "/") + ".class");
        ByteArrayOutputStream byteSt = new ByteArrayOutputStream();
        int len = 0;
        try {
            while ((len = is.read()) != -1) {
                byteSt.write(len);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return byteSt.toByteArray();
    }

}
  1. 測試類
public class Test {

    public static void main(String[] args) throws Exception {
        Test.test1();
        System.out.println("=========================");
        Test.test2();
    }

    private static void test1() throws Exception {
        MyClassLoader loader = new MyClassLoader();
        Class<?> c = loader.loadClass("testJvm.Man");
        System.out.println("Loaded by :" + c.getClassLoader());

        Parent p;
        System.out.println("Parent.class Loaded by :" + Parent.class.getClassLoader());
        Object parent = c.newInstance();
        System.out.println("c.newInstance() Loaded by :" + parent.getClass().getClassLoader());
        System.out.println("parent instanceof Parent :" + String.valueOf(parent instanceof Parent));
        p = (Parent) parent;
        System.out.println("p.getClass() Loaded by :" + p.getClass().getClassLoader());
        p.say();

        Man m;
        System.out.println("Man.class Loaded by :" + Man.class.getClassLoader());
        Object man = c.newInstance();
        System.out.println("c.newInstance() Loaded by :" + man.getClass().getClassLoader());
        System.out.println("man instanceof Man :" + String.valueOf(man instanceof Man));
        m = (Man) man;
        System.out.println("m.getClass() Loaded by :" + m.getClass().getClassLoader());
        m.say();
    }

    private static void test2() throws Exception {
        MyClassLoader loader = new MyClassLoader();
        Class<?> c = loader.findClass("testJvm.Man");
        System.out.println("Loaded by :" + c.getClassLoader());

        Parent p;
        System.out.println("Parent.class Loaded by :" + Parent.class.getClassLoader());
        Object parent = c.newInstance();
        System.out.println("c.newInstance() Loaded by :" + parent.getClass().getClassLoader());
        System.out.println("parent instanceof Parent :" + String.valueOf(parent instanceof Parent));
        p = (Parent) parent;
        System.out.println("p.getClass() Loaded by :" + p.getClass().getClassLoader());
        p.say();

        Man m;
        System.out.println("Man.class Loaded by :" + Man.class.getClassLoader());
        Object man = c.newInstance();
        System.out.println("c.newInstance() Loaded by :" + man.getClass().getClassLoader());
        System.out.println("man instanceof Man :" + String.valueOf(man instanceof Man));
        m = (Man) man;
        System.out.println("m.getClass() Loaded by :" + m.getClass().getClassLoader());
        m.say();
    }
}

結果:

Loaded by :sun.misc.Launcher$AppClassLoader@18b4aac2
Parent.class Loaded by :sun.misc.Launcher$AppClassLoader@18b4aac2
c.newInstance() Loaded by :sun.misc.Launcher$AppClassLoader@18b4aac2
parent instanceof Parent :true
p.getClass() Loaded by :sun.misc.Launcher$AppClassLoader@18b4aac2
hi, I'm a boy!
Man.class Loaded by :sun.misc.Launcher$AppClassLoader@18b4aac2
c.newInstance() Loaded by :sun.misc.Launcher$AppClassLoader@18b4aac2
man instanceof Man :true
m.getClass() Loaded by :sun.misc.Launcher$AppClassLoader@18b4aac2
hi, I'm a boy!
=========================
my class loader find class
Loaded by :testJvm.MyClassLoader@5680a178
Parent.class Loaded by :sun.misc.Launcher$AppClassLoader@18b4aac2
c.newInstance() Loaded by :testJvm.MyClassLoader@5680a178
parent instanceof Parent :true
p.getClass() Loaded by :testJvm.MyClassLoader@5680a178
hi, I'm a boy!
Man.class Loaded by :sun.misc.Launcher$AppClassLoader@18b4aac2
c.newInstance() Loaded by :testJvm.MyClassLoader@5680a178
man instanceof Man :false
Exception in thread "main" java.lang.ClassCastException: testJvm.Man cannot be cast to testJvm.Man
	at testJvm.Test.test2(Test.java:54)
	at testJvm.Test.main(Test.java:8)

在這裏插入圖片描述
第一個例子是自定義類加載器委託AppClassLoader對類進行加載,第二個例子是採用自定義類加載器本身對子類進行加載。
從第二個例子可以看出,雖然子加載器和父類加載器分別加載了Man這個類,但這兩個類由於命名空間不同,所以不能相互轉換。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章