深刻理解J2EE服务器类加载架构
1.类加载是一种父子树形结构
2.父加载器是无法看到子加载器加载的类
3.如果同一个类被两个没有父子关系的并行同时加载,每个加载器有自己的实例,两个实例类型不兼容。
不同服务器不同类加载原理,文章讨论了WebLogic 6.1 with Service Pack 2 和WebSphere 4.0的classloader原理
http://www.theserverside.com/tt/articles/article.tss?l=ClassLoading
1.类加载是一种父子树形结构
2.父加载器是无法看到子加载器加载的类
3.如果同一个类被两个没有父子关系的并行同时加载,每个加载器有自己的实例,两个实例类型不兼容。
不同服务器不同类加载原理,文章讨论了WebLogic 6.1 with Service Pack 2 和WebSphere 4.0的classloader原理
http://www.theserverside.com/tt/articles/article.tss?l=ClassLoading
首先,jdk考虑到不同app需要定制自己的classloader的情况(比如web应用),所以优先使用了thead的context classloader去加载类或者资源--如果只是使用class.forName,那么像这类需要加载具体实现的应用就只能在system classloader里找了,而具体实现(或者是实现的配置文件)可能在定制的classloader中(比如tomcat 的lib里面)。因此,jdk保证了我们在定制的classloader(比如web container)下也能正常使用使用xml解析器 :)
此外,在定制的classloader下加载自定义类时,万一调用者是system classloader的类时,使用class.forName就会找不到你的类--因为你的自定义类不在类路径里,这个时候也需要使用context classloader(不过这种情况比较少,主要可能是调用了系统的类来加载自定义的类,但是如果系统类没有使用context classloader那也无济于事:( 前一段时间用了jaxb,好像就没有用context classloader来加载类...)。
一般的classloader应该都需要用parent来优先代理查找类,这样才能保证加载层次逻辑上正确;所以context classloader应该是语义上最接近你的调用的loader,包含了相对最多的资源。
不知道理解的对不对*-) ...
以下是一点说明性的代码
|
[该贴被floydd于2007年01月26日 00:16修改过]
[该贴被floydd于2007年01月26日 00:18修改过]
比如:
Class.forName("java.lang.String");
和
String a ="";
加载方式是一样的。
所以,如果框架classloader层级关系复杂的话,就需要非常注意各个classloader之间的边界了
能否用类似如下的代码解决帖子中点到的问题呢?(尽管作为新人尚未看懂帖子的问题实指...)
try {
return Class.forName(className,
true,
Thread.currentThread().getContextClassLoader());
} catch (ClassNotFoundException e) {...throw e;}
可能是理解的不清晰吧(比如forName签名参数中的第二个boolean含义),所以也拟像您一样待到若干年后再回望此回复或许会领会与感悟.
1 Bootstrp loader
Bootstrp加载器是用C++语言写的,它是在Java虚拟机启动后初始化的,它主要负责加载%JAVA_HOME%/jre/lib以及%JAVA_HOME%/jre/classes中的类,并且它也会加载ExtclassLoader类。
2 ExtClassLoader
Bootstrp loader加载ExtClassLoader,并且将ExtClassLoader的父加载器设置为Bootstrp loader.当时因为bootstrp loader不是JAVA写的,所以占在JAVA的角度来看,调用Extclassloader的getParent()返回的是null.ExtClassLoader主要加载%JAVA_HOME%/jre/lib/ext中的jar文档,以及此路径下的所有classes目录。
3 AppClassLoader
Bootstrp loader加载完ExtClassLoader后,就会加载AppClassLoader,并且将AppClassLoader的父加载器指定为ExtClassLoader。AppClassLoader主要负责加载classpath所指定的位置的类或者是jar文档。
4 URLClassLoader
URLClassLoader是我们可以自定义的加载器,我们可以通过指定一个URL对象来创建此加载器,它所加载路径就是URL所代表的逻辑位置。并且它的父加载器是AppClassLoader。
有了这个加载器的继承体系以后,就可以清楚的知道委托模型是怎么实现的了,当一个加载器要加载一个类的时候,首先请求父加载器来加载,父加载器再请求父加载器来加载,依此类推,如果所有的父加载器都不能加载,那么才有自己加载,如果也不能加载,则出现NoClassDefFoundError错误.所以打包的时候,其实是将自己的类放在规定的地方,让框架已经实现的类加载器来加载,这样以来,就可以让框架来管理自己些的类的生命周期。在一般的情况下,我们自己写的类,默认都是由AppclassLoader来载入的,只要class的全名不和AppclassLoader的父加载器已经加载的类相同就OK。