jvm classloader 原理

1,类加载器构成
Bootstrap(启动类加载器 $JAVA_HOME/lib)---extension(ExtClassLoader扩展类加载器$JAVA_HOME/lib/ext)---system(AppClassLoader系统类加载器Classpath)
2,加载机制
双亲委派机制,某个特定的类加载器接受到加载请求时,首先将加载请求委托给父类加载器,一次递归,父类加载器可以完成加载任务,则成功返回,只有父类无法完成加载时,才自己去加载,jvm默认的双亲委派机制通过ClassLoader的loadClass方法来实现的。方法如下


// 首先判断该类型是否已经被加载

        Class c = findLoadedClass(name);

        if (c == null) {

            //如果没有被加载,就委托给父类加载或者委派给启动类加载器加载

            try {

                if (parent != null) {

//如果存在父类加载器,就委派给父类加载器加载

                    c = parent.loadClass(name, false);

                } else {

//如果不存在父类加载器,就检查是否是由启动类加载器加载的类,通过调用本地方法native Class findBootstrapClass(String name)

                    c = findBootstrapClass0(name);

                }

            } catch (ClassNotFoundException e) {

        // 如果父类加载器和启动类加载器都不能完成加载任务,才调用自身的加载功能

                c = findClass(name);

            }

        }


注意:扩展类加载器的父加载器为为NUL,引导类加载器涉及到虚拟机本地实现细节,开发者无法直接获取到启动类加载器的引用


如何实现我们的自定义类加载器呢?

实现自定义加载器其它很简单。只要实现ClassLoader的findClass()方法就行了。

大概如下:

findClass(String name){

    byte[] buffer=//读取文件的字节数组

    return defineClass(buffer,0,buffer.length);

}



当自定义类加载器加载的类有继承相应的类或实现相应接口的话,必须把相应的父类或接口拷贝到同一路径。因为类加载器在加载子类时,会同时加载父类。

关于类的转型问题:

由于类加载器是相互隔离的,当classLoaderA加载了A类,classLoaderB也加载了A类。这个类对象是不能互相转型的。会报ClassCastException异常。

假如自定义类加载器加载A类时,而A类又实现了接口B时,我们是可以将A类的实例转成B接口的。原因是类加载器在加载A类时,会同时加载A类的所有父类(包括接口).

JAVA类加载器采用了委托模式。当一个类对象己经被加载了,就不会在去加载该类。还是直接返回。那么如何重新加载这个类呢?

实现自定义的类加载器,当类加载完成后。调用相应方法,然后在去掉相应类加载器的引用。这样类不会在存在类加载器中了。

比如:classLoaderA=null(去掉A加载器的引用)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值