[自定义类加载器]

目录

[类中对类的主动使用触发的类加载]

[不同命名空间类的可见性]


 

public class TestClassLoader extends ClassLoader {
    @Override
    protected Class<?> findClass(String name) throws ClassNotFoundException {
        System.out.println("进入自定义加载器");
        byte[] data = loadClassData();
        return this.defineClass(name, data, 0, data.length);
    }

    /**
     * 读取编译好的.class文件返回对应的字节数组
     */
    private byte[] loadClassData() {
        InputStream in = null;
        byte[] data = null;
        ByteArrayOutputStream baos = null;

        try {
            in = new FileInputStream(new File("/Users/wangbo/Downloads/code/my/classfile/bobo.class"));

            baos = new ByteArrayOutputStream();

            int ch = 0;
            while (-1 != (ch = in.read())) {
                baos.write(ch);
            }
            data = baos.toByteArray();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                in.close();
                baos.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return data;
    }

    public static void main(String[] args) throws Exception {

        //不注释下面的bobo类,因为会使用appclassload加载bobo.class,所以虽然下面二个类加载器实例不是同一个命名空间下,但是class只会被加载一次
        //注释bobo类,系统类加载器找不到bobo会调用我自定义的类加载器,二个不同的命名空间,class会被二个加载器都加载一次
        //自下而上树形查找是否加载过
        TestClassLoader testClassLoader = new TestClassLoader();
        //loadClass并不会导致对该类的初始化
        Class<?> calss = testClassLoader.loadClass("com.notecode.test.bobo");
        Object o = calss.newInstance();
        System.out.println("calss对象:" + calss.hashCode());
        System.out.println("实例对象:" + o);
        System.out.println("类加载器:" + o.getClass().getClassLoader());

        TestClassLoader testClassLoader2 = new TestClassLoader();
        Class<?> calss2 = testClassLoader2.loadClass("com.notecode.test.bobo");
        Object o2 = calss2.newInstance();
        System.out.println("calss对象:" + calss2.hashCode());
        System.out.println("实例对象:" + o2);
        System.out.println("类加载器:" + o2.getClass().getClassLoader());

    }
}

//class bobo{
//
//}

[类中对类的主动使用触发的类加载]

public static void main(String[] args) throws Exception {
        
        //运行会报错       Caused by: java.lang.ClassNotFoundException: com.notecode.test.bobo
        //错误分析:
        // 根据双亲委派机制,bobo1.class的文件路径在classpath下,所以是系统类加载器去加载
        // bobo1的构造方法中调用了bobo类,造成其主动使用,所以会触发加载
        // 会使用加载bobo1的系统类加载器去加载bobo,所以报错
        
        TestClassLoader testClassLoader = new TestClassLoader();
        Class<?> calss = testClassLoader.loadClass("com.notecode.test.bobo1");
        Object o = calss.newInstance();
        System.out.println("calss对象:" + calss.hashCode());
        System.out.println("实例对象:" + o);
        System.out.println("类加载器:" + o.getClass().getClassLoader());

    }
}


class bobo1{
    bobo1(){
        //存在在磁盘外的class文件
        new bobo();
        System.out.println("bobo1构造器");
    }
}

[不同命名空间类的可见性]

 public static void main(String[] args) throws Exception {

        //运行结果:
        // calss对象:500977346
        //实例对象:com.notecode.test.bobo@133314b
        //类加载器:com.notecode.test.TestClassLoader@9807454
        //sun.misc.Launcher$AppClassLoader@18b4aac2
        //Exception in thread "main" java.lang.NoClassDefFoundError: com/notecode/test/bobo


        //错误分析
        //命名空间的导致的可见性问题
        //因为加载bobo1的是系统类加载器,其父是看不见子所加载的类
        //小技巧:类中创建和查找其他类的时候,都用的是当前类的命名空间

        TestClassLoader testClassLoader1 = new TestClassLoader();
        Class<?> calss1 = testClassLoader1.loadClass("com.notecode.test.bobo");
        Object o1 = calss1.newInstance();
        System.out.println("calss对象:" + calss1.hashCode());
        System.out.println("实例对象:" + o1);
        System.out.println("类加载器:" + o1.getClass().getClassLoader());


        TestClassLoader testClassLoader = new TestClassLoader();
        Class<?> calss = testClassLoader.loadClass("com.notecode.test.bobo1");
        Object o = calss.newInstance();
        System.out.println("calss对象:" + calss.hashCode());
        System.out.println("实例对象:" + o);
        System.out.println("类加载器:" + o.getClass().getClassLoader());


    }
}

class bobo1{
    bobo1(){
        System.out.println(bobo1.class.getClassLoader());
        //磁盘外的class文件
        System.out.println(bobo.class);
    }
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值