您的位置:首页 > 其它

JVM学习笔记(三)---类加载器补充

2016-01-15 14:47 232 查看
类加载器自上而下的分为

bootstrap classloader -> ext classloader -> system classloader ->user defined classloader

       除了bootstrap classloader在代码层面无法获得其引用外,其余都可以通过ClassLoader.getSystemClassLoader()获得系统class loader后通过getParent()获得其父class loader. 其loadClass方法用来load对应的class,先判断class loader的cache里是否有对应的class,若没有则先让其父class
loader尝试load,若没有父class loader则说明其父class loader为bootstrap classloader,若父class loader依然load不到,则调用findClass方法load,子类class loader可以继承ClassLoader类重写findClass方法自定义类加载规则,当然也可以直接重写loadClass方法打破父classloader控制的责任链。因此有必要介绍一下Thread.currentThread().getContextClassLoader(),默认为system
class loader,由launcher指定

     这里怎么又出来一个context classloader呢?它有什么用呢?我们在建立一个线程Thread的时候,可以为这个线程通过setContextClassLoader方法来 指定一个合适的classloader作为这个线程的context classloader,当此线程运行的时候,我们可以通过getContextClassLoader方法来获得此context
classloader,就可以用它来载入我们所需要的Class。默认的是system classloader。利用这个特性,我们可以“打破”classloader委托机制了,父classloader可以获得当前线程的context classloader,而这个context classloader可以是它的子classloader或者其他的classloader,那么父classloader就可以从其获得所需的 Class,这就打破了只能向父classloader请求的限制了。这个机制可以满足当我们的classpath是在运行时才确定,并由定制的
classloader加载的时候,由system classloader(即在jvm classpath中)加载的class可以通过context classloader获得定制的classloader并加载入特定的class(通常是抽象类和接口,定制的classloader中是其实现),例 如web应用中的servlet就是用这种机制加载的.

如此以来有如下总结:

1. 对应不同的类加载器加载同一个class文件(类名,包名都想通),其可以在同一个虚拟机中,有两个类

2. 为了防止第一种情况发生,需要使用父子类加载器责任链模式,任何类加载前先走父加载器

3. 可以采用URLClassLoader并指明搜索的classpath url,默认情况下其会用当前线程的contextClassLoader作为其父classLoader

4. 最后调用loadClass加载指明url中的类

github参考代码 https://github.com/hzllblzjily/udclassloader
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息