最近在做一个项目,综合使用了jboss的microcontainer,jetty和自己定义的war包,war包中还会用到spring,因为牵涉到多个容器,同时又有自己的自定义类,所以classloader环境异常复杂,ClassNotFound问题搞得头都大了,最后综合各种因素,设计了如下的一个classloader层次:
其中,红色部分是系统(也就是启动java程序加载Main函数的classloader),主要的设计考量有以下几点:
1、使用自定义的ExtClassLoader(加载java的ext目录下的jar包)把程序加载的class完全和系统加载的class隔离开,这样即使在eclipse容器中启动都不会有类冲突。
为什么不从系统的ExtClassLoader作为自定义classloader数的根有两个考虑,第一个是系统ExtClassLoader有可能不存在,第二个就是如果使用同一个ExtClassLoader中,在处理JNDI、XML和URL解析等java扩展功能时会遇到后加载的handler部分导致不同classloader树加载的同一个类的ClassCastException,具体参见这些模块的源代码。
2、WarClassLoader除了系统类和Common类(目前只有log相关类)以外的类都从war包的WEB-INFO和classes下加载。
3、所有执行War包中代码的线程ThreadContextClassLoader都设置为WarClassLoader,以供Spring和Webx中的相关工具类使用这个classloader结构的后门来加载war包中的类,典型例子是Webx中ResourceLoaderService就是使用ContextClassLoader来加载类的。
4、RialtoClassLoader也就是这个项目的容器加载器和WarClassLoader不在同一个树路径上,可以避免程序使用类和war使用类的class冲突,典型的是Spring容器相关代码。
5、CommonClassLoader加载的类需要严格控制,否则可能会导致运行期类冲突,例如Spring的相关jar包绝对不可以出现在这个classloader作用范围内。
总之,ClassLoader采用父分派机制,后来增加的Thread ContextClassLoader在这个体系上增加了一个后门,带来了灵活性,也带来了很多令人困扰的问题,在做容器类的项目时难免会遇到class loader层次设计的问题,这里抛砖引玉,欢迎达人拍砖。
posted on 2010-07-14 19:18
井底青蛙,常望天空 阅读(1061)
评论(0) 编辑 收藏 所属分类:
java