双亲委派模型
类加载器之间的这种层次关系叫做双亲委派模型。 双亲委派模型要求除了顶层的启动类加载器(Bootstrap ClassLoader)外,其余的类加载器都应当有自己的父类加载器。这里的类加载器之间的父子关系一般不是以继承关系实现的,而是用组合实现的。
双亲委派模型的工作过程
由我来概况就是 八个字 向上检查,从下加载
如果一个类接受到类加载请求,他自己不会去加载这个请求,而是将这个类加载请求委派给父类加载器,这样一层一层传送,直到到达启动类加载器(Bootstrap ClassLoader)。 只有当父类加载器无法加载这个请求时,子加载器才会尝试自己去加载。
双亲委派模型的代码实现
双亲委派模型的代码实现集中在java.lang.ClassLoader的loadClass()方法当中。
- 首先检查类是否被加载,没有则调用父类加载器的loadClass()方法;
- 若父类加载器为空,则默认使用启动类加载器作为父加载器;
- 若父类加载失败,抛出ClassNotFoundException 异常后,再调用自己的findClass() 方法。
loadClass源代码如下:
protected synchronized Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException { //1 首先检查类是否被加载 Class c = findLoadedClass(name); if (c == null) { try { if (parent != null) { //2 没有则调用父类加载器的loadClass()方法; c = parent.loadClass(name, false); } else { //3 若父类加载器为空,则默认使用启动类加载器作为父加载器; c = findBootstrapClass0(name); } } catch (ClassNotFoundException e) { //4 若父类加载失败,抛出ClassNotFoundException 异常后,这个方法就是加载的核心代码 c = findClass(name); } } if (resolve) { //5 再调用自己的findClass() 方法。 resolveClass(c); } return c; } 复制代码
自定义类加载器
class NetworkClassLoader extends ClassLoader { * String host; * int port; * * public Class findClass(String name) { * byte[] b = loadClassData(name); * return defineClass(name, b, 0, b.length); * } * * private byte[] loadClassData(String name) { * // load the class data from the connection * . . . * } * } 复制代码
这个就是官方的例子
破环双亲委派
双亲委派模型很好的解决了各个类加载器加载基础类的统一性问题。即越基础的类由越上层的加载器进行加载。 若加载的基础类中需要回调用户代码,而这时顶层的类加载器无法识别这些用户代码,怎么办呢?这时就需要破坏双亲委派模型了。
java默认的线程上下文类加载器是系统类加载器(AppClassLoader).
// Now create the class loader to use to launch the application try { loader = AppClassLoader.getAppClassLoader(extcl); } catch (IOException e) { throw new InternalError( "Could not create application class loader" ); } // Also set the context class loader for the primordial thread. Thread.currentThread().setContextClassLoader(loader); 复制代码
以上代码摘自sun.misc.Launch的无参构造函数Launch()。
使用线程上下文类加载器,可以在执行线程中,抛弃双亲委派加载链模式,使用线程上下文里的类加载器加载类.
典型的例子有,通过线程上下文来加载第三方库jndi实现,而不依赖于双亲委派.
大部分java app服务器(jboss, tomcat..)也是采用contextClassLoader来处理web服务。
结尾
今天把类加载机制好好讲了一下,这样大家就更加的熟悉了内的加载过程,对于Java开发是有好处的