java虚拟机 之 类加载器

参考 <<深入理解java虚拟机 JVM高级特性与最佳实践>>

什么是类加载器?
是一组代码,通过类的全限定名来获取描述此类的二进制字节流信息。让应用程序来决定如何去获取所需要的类。
应用场景:类层次划分,OSGI, 热部署, 代码加密
用于类加载流程中的加载阶段。

 对于任意一个类,都需要由它的类加载器和这个类本身一同确立其在java虚拟机中的唯一性
 如下代码:
 public static void main(String[] args) {
        ClassLoader myclassLoader = new ClassLoader() {
            @Override
            public Class<?> loadClass(String name) throws ClassNotFoundException {
                try {
                    String fileName = name.substring(name.lastIndexOf(".")+1)+".class";

                    InputStream in = getClass().getResourceAsStream(fileName);
                    if(in == null){
                        return super.loadClass(name);
                    }
                    byte[] b = new byte[in.available()];
                    in.read(b);
                    return defineClass(name, b, 0, b.length);
                } catch (IOException e) {
                    throw new ClassNotFoundException(name);
                }
            }
        };
        try {
            Object o = myclassLoader.loadClass("com.tiany.test.ClassloaderTest").newInstance();
            System.out.println("ClassloaderTest -->"+o.getClass());
            System.out.println(o instanceof com.tiany.test.ClassloaderTest);
            Object object = myclassLoader.loadClass("com.tiany.lock.TwinsLock").newInstance();
            System.out.println("TwinsLock-->"+object.getClass());
            System.out.println(object instanceof com.tiany.lock.TwinsLock);
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
输出结果:
ClassloaderTest -->class com.tiany.test.ClassloaderTest
false
TwinsLock-->class com.tiany.lock.TwinsLock
true

问题1 
 只有当前main方法所在的类用自定义的加载器加载出来的才是不同的,但其它的类加载却是返回true的。
无论我调整自定义加载器myclassLoader的位置(放置到另一个类中),结果都与上面结果一样。

jvm中类加载器的种类

  1. BootStrapLoader 启动类加载器 会加载一些JVM自身运行所需的class
  2. ExtClassLoader 扩展类加载器 会加载指定目录下一些特殊的class
  3. AppClassLoader 应用程序加载类 会加载classpath路径下的class,以及main函数所在的类的class文件。

    加载的方式:
    双亲委派模式

如果一个类加载器受到了类加载的请求,首先不会自己加载这个类,每一个层次的类加载器都是如此,所有的加载器最终都会传送到最顶层的BootStapLoader加载器中,只有当父加载器反馈自己无法完成这个加载请求(它的搜索范围中没有找到所需的类)时,子加载器才会尝试自己去加载。

回到上面代码中的问题1:
假设:

主线程 main 启动首先会对ClassLoaderTest进行加载,用的是appClassLoader.
定义自己的加载器后myClassLoader后,调用父类加载器无法完成加载(没有在父类加载器范围内找到这个类),只能通过自定义的加载器进行加载,所以instanceof 判断是两个不同的类
而其它的类都是jvm启动后使用时才进行加载的。原本方法区可能没有这个类,自定义的加载也能调用父类的加载成功,所以它的类型是一致的。

测试:


在loadClass方法中加上
Class clazz = super.findLoadedClass(name);
                if(clazz == null){
                    System.out.println(name+"还未被加载");
                }else {
                    System.out.println(name + "已经被加载过了");
                }

结果:
com.tiany.test.ClassloaderTest$1还未被加载
ClassloaderTest -->class com.tiany.test.ClassloaderTest
false
com.tiany.lock.TwinsLock还未被加载
TwinsLock-->class com.tiany.lock.TwinsLock
true

根据当前的名称加载的居然是ClassloaderTest的内部类,而且不是ClassloaderTest本身
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值