自定义ClassLoader测试

本文参考‘深入分析ClassLoader’博客,对例子进行详细解析。包含Parent接口、Man实现类等。介绍了自定义类加载器委托加载类和本身加载子类的例子,指出因命名空间不同,子父加载器加载的类不能相互转换,还展示了不同类加载器加载父类和子类的结果。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

参考博客:
深入分析ClassLoader

在阅读文章后,对例子进行更详细的解析。

  1. Parent接口
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("Man");
        System.out.println("Loaded by :" + c.getClassLoader());

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

        System.out.println("Man.class Loaded by :" + Man.class.getClassLoader());
        System.out.println("man instanceof Man :" + String.valueOf(man instanceof Man));
        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("Man");
        System.out.println("Loaded by :" + c.getClassLoader());

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

        System.out.println("Man.class Loaded by :" + Man.class.getClassLoader());
        Man m = new Man();
        System.out.println("m Loaded by:" + m.getClass().getClassLoader());
        System.out.println("man 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
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 :MyClassLoader@14ae5a5
Parent.class Loaded by :sun.misc.Launcher$AppClassLoader@18b4aac2
c.newInstance() Loaded by :MyClassLoader@14ae5a5
man instanceof Parent :true
p.getClass() Loaded by :MyClassLoader@14ae5a5
hi, I'm a boy!
Man.class Loaded by :sun.misc.Launcher$AppClassLoader@18b4aac2
m Loaded by:sun.misc.Launcher$AppClassLoader@18b4aac2
man Loaded by :MyClassLoader@14ae5a5
man instanceof Man :false
Exception in thread "main" java.lang.ClassCastException: Man cannot be cast to Man
	at Test.test2(Test.java:47)
	at Test.main(Test.java:6)

在这里插入图片描述
第一个例子是自定义类加载器委托AppClassLoader对类进行加载,第二个例子是采用自定义类加载器本身对子类进行加载。
从第二个例子可以看出,虽然子加载器和父类加载器分别加载了Man这个类,但这两个类由于命名空间不同,所以不能相互转换。

继续来点刺激的,将parent声明为class,先后用类加载器加载父类和子类:

private static void test3() throws ClassNotFoundException, IllegalAccessException, InstantiationException {
        MyClassLoader loader = new MyClassLoader();

        Class<?> parentClzz = loader.findClass("Parent");
        Class<?> manClzz = loader.findClass("Man");

        Object man = manClzz.newInstance();
        Object parent = parentClzz.newInstance();
        System.out.println(man instanceof Man);
        System.out.println(parent instanceof Parent);
        System.out.println(man instanceof Parent);

        System.out.println(Man.class.getClassLoader());
        System.out.println(Parent.class.getClassLoader());

        System.out.println(man.getClass().getClassLoader());
        System.out.println(parent.getClass().getClassLoader());
    }

结果:

false
false
false
sun.misc.Launcher$AppClassLoader@18b4aac2
sun.misc.Launcher$AppClassLoader@18b4aac2
MyClassLoader@7f31245a
MyClassLoader@7f31245a

换成两个类加载器,分别加载父类和子类:

private static void test4() throws ClassNotFoundException, IllegalAccessException, InstantiationException {
        MyClassLoader loader = new MyClassLoader();
        MyClassLoader2 loader2 = new MyClassLoader2();

        Class<?> parentClzz = loader.findClass("Parent");
        Class<?> manClzz = loader2.findClass("Man");

        Object man = manClzz.newInstance();
        Object parent = parentClzz.newInstance();
        System.out.println(man instanceof Man);
        System.out.println(parent instanceof Parent);
        System.out.println(man instanceof Parent);

        System.out.println(Man.class.getClassLoader());
        System.out.println(Parent.class.getClassLoader());

        System.out.println(man.getClass().getClassLoader());
        System.out.println(parent.getClass().getClassLoader());
    }

结果:

false
false
true
sun.misc.Launcher$AppClassLoader@18b4aac2
sun.misc.Launcher$AppClassLoader@18b4aac2
MyClassLoader2@45ee12a7
MyClassLoader@7f31245a

哦吼,是不是很刺激?

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值