作者:王东明 —
上次修改时间: 2007-11-09 11:01
Apusic应用服务器目前在默认情况下是三层类装在体系(具体介绍可参考知识库中的相关文档)。但是,默认情况下,因为用户的应用部署并不是一个理想状况,他的一个相同的类,经常部署到jar包中,同时又在classes中存在,因此三层类装载体系下,经常出现ClassNotFound的情况。
典型的情况是:在很多的用户代码中,由于用户代码的设计考量不完善,经常出现部署在WEB-INF/lib目录下jar中的类使用自身 ClassLoader装载WEB-INF/classes下的类,此时容出现ClassNotFound异常,而这种情况在很多客户应用中是相当普遍的。
但是,这种情况,在其他的应用服务器中却很少出现异常,据此,我们有一个参数可以对Apusic应用服务器的类装在体系进行设置,这样,可以很大程度上避免出现ClassNotFound的问题:
ServletClassLoader本身不再持有委派ClassLoader的实例,而持有一个delegate实例。所有行为都委派给delegate去完成,delegate有三种:
SeparatedLoaderDelegate 分jsp、WEB-INF/classes和WEB-INF/lib三个层次的类装载体系
IntegrateLoaderDelegate 分jsp和其他的两个层次的类装载体系
SimpleLoaderDelegate 不分层次,所有类由一个ClassLoader装载
有两种方式可以配置delegate的类型。
1、在web.xml中增加ContextInitParameter
<context-param>
<description>
</description>
<param-name>com.apusic.web.ServletClassLoaderDelegate</param-name>
<param-value>
com.apusic.servlet.http.IntegrateLoaderDelegate</param-value>
</context-param>
这样的配置有效范围只有当前应用
2、通过VM参数指定 -Dcom.apusic.web.ServletClassLoaderDelegate=com.apusic.servlet.http.IntegrateLoaderDelegate
这个配置,所有的应用都适用
两种都指定的情况下,以web.xml中定义的为准
没有任何配置,使用默认的SeparatedLoaderDelegate
注意,直到本篇文档发稿为止(20071030),对于资源文件的处理在两层和一层结构下,如果在jar包和classes都存在该文件的情况下,先读到是jar包中的资源文件。对于class则是先读到的是classes中的。
[杨威补充]:
一个错误的重现:在开源项目tobago中,访问http://localhost:6888/tobago/faces/overview/toolbar.jsp时会报java.lang.ClassNotFoundException: org.apache.myfaces.tobago.example.demo.actionlistener.SimpleTabChangeListener错误。
错误原因:jar包中的TabChangeListenerTag类调用createTabChangeListener时,要访问classes目录下的SimpleTabChangeListener类。由于类装载机制,部署在WEB-INF/lib目录下jar中的类使用自身ClassLoader 装载WEB-INF/classes下的类会出现ClassNotFound。
解决方法的补充:
Apusic4.x startapusic中添加启动参数:
-Dcom.apusic.web.ServletClassLoaderDelegate=com.apusic.servlet.http.IntegrateLoaderDelegate
Apusic5.1 startapusic中添加启动参数:
-Dcom.apusic.web.ServletClassLoaderDelegate=com.apusic.web.container.IntegrateLoaderDelegate