最近去了解了下关于java虚拟机中的加载机制,特地写了篇blog来记忆下。
首先我们来了解下概念,什么是类加载器?
A:加载器就是把java的字节码从硬盘中加载到内存,然后再做一些处理,这就是类加载器所做的一些工作
默认情况下:java有默认的三个类加载器,(树状结构)从上到下分别是bootStrap、ExtClassLoader、AppClassLoader三个加载器
本质上java的类加载器为一个java类,当然也有一个是特殊的,就比如说第一个加载器bootStrap是用C++写的
优先级是从上到下:可以看下代码了解下:
package zju.zsq.day01; public class ClassLoaderTest { public static void main(String[] args) { System.out.println( ClassLoaderTest.class.getClassLoader() .getClass().getName()); System.out.println( System.class.getClassLoader() ); ClassLoader loader = ClassLoaderTest.class.getClassLoader(); //看下树状结构,如果为null就代表找不到java的class文件,等于找到了bootstrap(C++实现的加载) while(loader != null){ System.out.println(loader.getClass().getName()); loader = loader.getParent(); } System.out.println(loader); /** * AppClassLoader:只从classpath指定的目录或者jar包下面加载类 * ExtClassLoader:JRE/lib/ext/*.jar * BootStrap:专门加载JRE/lib/rt.jar */ } }
bootStrap:
ExtClassLoader:
AppClassLoader:
说了那么多,让我们看看java虚拟机加载一个类的时候,到底派出哪个类加载器去加载呢?
一般来说当前线程的类加载器去加载线程中的第一个类, 比如说当前的
ClassLoaderTest类,他是先让appClassLoader去加载,然后,appClassLoader委托给extClassLoader加载,然后extClassLoader委托给bootStrap加载,
而bootStrap找不到加载,又扔给extClassLoader加载,extClassLoader同样加载不了,又委托给appClassLoader加载,而appClassLoader刚好可以加载,就加载完成了
当然,如果说前面的爷爷,或者爸爸可以加载就不会让树状图下面的家宅器来加载了。如果到了appClassLoader还加载不了,那么就是runtimeError(classNotFoundException)
这就是委托机制,可以方便集中管理,不会生成多分字节码(class文件)
当然比如说当前线程是ClassLoaderTest类。那么,
如果ClassLoaderTest类引用了B类,那么就用ClassLoaderTest类的加载器去加载B类。
也可以直接调用哪个类加载器来加载 如 ClassLoader.loadClass()来指定具体某个加载器来加载类
我还记得有一道面试题特别经典。
就是能不能自己重写java.lang.System
我觉得吧,应该这样回答。当然是可以,但是你写了也是白写,因为重写后,根据委托机制,最后调用的还是系统原来的
除非自己写一个类加载器,而且这个类加载器还要比较特殊,要抛开委托机制。
我觉得应该是这样答的,
原文:http://blog.csdn.net/zsq66zsq/article/details/38677151