JVM的classloader(转)

Java中一共有四个类加载器,之因此叫类加载器,是程序要用到某个类的时候,要用类加载器载入内存。
    这四个类加载器分别为:Bootstrap ClassLoaderExtension ClassLoaderAppClassLoader
URLClassLoader,他们的做用其实从名字就能够大概推测出来了。其中AppClassLoader在不少地方被叫作System ClassLoader

Bootstrap ClassLoader是在JVM开始运行的时候加载java的核心类,是用C++编写的,它用来加载核心类库,在JVM源代码中这样写道:
static const char classpathFormat[] =
"%/lib/rt.jar:"
"%/lib/i18n.jar:"
"%/lib/sunrsasign.jar:"
"%/lib/jsse.jar:"
"%/lib/jce.jar:"
"%/lib/charsets.jar:"
"%/classes";
Extension ClassLoader是用来加载扩展类,即/lib/ext中的类。
AppClassLoader用来加载Classpath的类,是和咱们关系最密切的类。
URLClassLoader用来加载网络上远程的类,暂且不讨论。

它们之间的关系:

1.Parent-Child,按顺序从大到小。不是简单的继承关系。

2.ClassLoader有个getParent的方法,可是Ext ClassLoader调用后获得的是null,bootstrap是JVM本身的,用户看不到。

3.classloader的委托机制:当等级比较低的ClassLoader要加载某个类的时候,它首先会请求Parent加载器来加载,Parent再请求它的Parent
好比如今Ext要加载了,它往上请求。若是最大的Bootstrap找不到,那么Boot会叫Ext本身找找,Ext找不到,是不会让下一级的App去找的,此时就报出ClassNotFoundException

4. 类A调用类B,B会要求调用它的类的类加载器来加载它,也就是B会要求加载A的加载器来加载B。这就会有个问题,若是他们在一块儿,那不要紧,确定某个 classloader会把它们俩都加载好。可是若是A在/lib/ext文件夹中,而B在Classpath中呢?过程是这样的首先加载A,那么一层层 上到Bootstrap Classloader,boot没找到因此ext本身找,找到了,没问题;加载B,由于A调用了B,因此也从bootstrap来找,没找到,而后A的 ext classloader来找仍是没找到,可是不再会往下调用了,因而报出ClassNotFoundException。
可是现实生活 中有不少应用,好比JDBC核心方法在核心库而驱动在扩展库,是一定在两个地方的,那怎么办呢?要用到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就是用这种机制加载的.java

 

http://hi.baidu.com/qmiao128/item/c983bffca5ca6fec1b111f26web

相关文章
相关标签/搜索