Java虚拟机中ClassLoader的机制分析
首先我们得明白什么是类加载器(ClassLoader):
A【类加载的作用】:java中的类加载器就是把java字节码(class文件)从硬盘中加载到内存中,然后做一些处理,这就是类加载器。
一般来说,类加载器本身是一个java类,但是BootStrap加载器是C++写成的。是所有加载器的根。
默认情况下,java提供了三个默认加载器:
- BootStrap:只从classpath指定的目录或者jar包下面加载类
- ExtClassLoader:加载JRE/lib/ext/*.jar
- AppClassLoader:专门加载JRE/lib/rt.jar
先看一段代码:
|
|
输出结果为:
|
|
从代码里面我们可以看到,从上到下加载器是成树状的(其中null为BootStrap,因为上诉代码得到的是classname,但是C++没有生产字节码,所以为null
),再让我们看看下图:
java虚拟机加载一个类的时候,到底派出哪个类加载器去加载呢?
A :一般来说是当前线程的类加载器去加载线程中的第一个类,Thread.currentThread().getContextClassLoader(),当然从上面的代码我可以知道加载ClassLoaderTest这个类是AppClassLoader加载器。具体来说,ClassLoaderTest用这个AppClassLoader加载器来加载,但是它不是立即就加载的 。过程如下:
- 1.ClassLoaderTest先找到他的加载器AppClassLoader
- 2.AppClassLoader就委托到父加载器ExtClassLoader加载
- 3.ExtClassLoader开始加载,找不到加载类,就开始委托给它的子加载器ExtClassLoader
- 4.ExtClassLoader开始加载,找不到加载类,就开始委托给它的子加载器AppClassLoader
- 5.AppClassLoader开始加载,找到加载,加载完毕。
这是一个委托机制,一般来说,先是从现在类的加载器,一层层委托到最顶层的加载器,然后顶层的加载器,开始加载,找不到加载类,就委托给下一层,如果在到当前类的加载器之前加载完毕,就结束。如果直到当前类还加载不了,就抛ClassNotFoundException。
这个委托机制的优点是:方便集权管理,比如说只有不会生成多份字节码。
在这里突然就想到了一份经典的面试题,能否自己重写Java.lang.system这个类
答案是当然可以,但是一般情况下写了也得于白写,当委托到最顶上的那个加载器就直接被加载了。除非自己写一个加载器,然后还要抛开委托机制。
好了,今天算是把加载器粗略的了解下,与诸君共勉!加油!