转自http://jingdewang2008.blog.sohu.com/94004192.html
Q:项目部署在linux的webLogic后由于jar包加载顺序的原因造成POI读取word报错,
java.lang.NoSuchMethodError: org.apache.poi.poifs.filesystem.POIFSFileSystem.getRoot()Lorg/apache/poi/poifs/filesystem/DirectoryNode;
在windows下是没有这个问题的。
经调查是poi的jar包加载顺序过于靠后,可能是会先调用某个包中的同名class。
不过项目已经发布,只能把poi的jar包全都扔到webLogic的lib里,
问题解决。
A:
行者孙:
类是通过类加载器classloader载入的。
缺省情况下web容器遵循java的标准标准类载入机制 -- 由现载入父加载器level的类。
weblogic的web容器的classloader继承自ejb容器的classloader,ejb容器的classloader又继承自application classloader--该loader负责加载classpath下面的类,所以缺省情况下classpath下面的类会被优先载入,即使相同的类存在于web应用的lib目录。
可以通过配置文件来修改这种加载顺序,使得lib目录中的类得到优先调用,在weblogic 8.1中,方法是在weblogic.xml中加入下面的代码段:
<container-descriptor>
<prefer-web-inf-classes>true</prefer-web-inf-classes>
</container-descriptor>
者行孙:
类加载的问题要想说明白估计要写上个几百字才能搞定,我懒,就简单说一下:)
calssloader分级别。weblogic中默认有以下几个级别:
1。系统类路径,除了java路径和java扩展路径,这个算是级别最高的了。
2。APP-INF/lib or APP-INF/classes,这个就和具体的应用相关了。也就是说两个或多个应用的APP-INF/LIB下的类是不可见的。比系统类路径的级别低了一级。
3。WEB-INF/lib or WEB-INF/classes,这个应该是最低的级别了。
classLoader在装载类的时间会从上而下的顺序来装载类。首先装载java自身的类(安全考虑),如果没有找到要装载的类,就查找java扩展路径下的类,如果还没找到就系统类路径,在然后 APP-INF/lib or APP-INF/classes,再然后WEB-INF/lib or WEB-INF/classes,如果找到你的包所在的层次还找不到要装载的类,嘿,你就会看到一个你比较熟悉的异常。
需要注意的是,ejb的jar包和web.war包是calssloader级别是一样的,级别一样的calssloader是不能相互装载的。所以ejb的jar包和web.war包中的类也是不可见的,也就是说子calssloader能装载父(包括父)以上层次下的类,而不能装载子层次和兄弟层次下的类。ejb的jar包和web.war包是兄弟层次。当然a.ear和b.ear也是兄弟层次。
也不知道说明白了没,我写的太少了,具体你还是找找资料吧。
孙行者:
BEA的官方介绍,可以到网站下这个文档。
WebLogic Server Application Classloader Overview
This section provides an overview of the WebLogic Server application classloaders.
Application Classloading
WebLogic Server classloading is centered on the concept of an application. An application is
normally packaged in an Enterprise Archive (EAR) file containing application classes.
Everything within an EAR file is considered part of the same application. The following may be
part of an EAR or can be loaded as standalone applications:
.. An Enterprise JavaBean (EJB) JAR file
.. A Web application WAR file
.. A resource adapter RAR file
Note: For information on Resource Adapters and classloading, see “About Resource Adapter
Classes” on page 4-15.
If you deploy an EJB and a Web application separately, they are considered two applications. If
they are deployed together within an EAR file, they are one application. You deploy modules
together in an EAR file for them to be considered part of the same application.
Every application receives its own classloader hierarchy; the parent of this hierarchy is the system
classpath classloader. This isolates applications so that application A cannot see the classloaders
or classes of application B. In hierarchy classloaders, no sibling or friend concepts exist.
Application code only has visibility to classes loaded by the classloader associated with the
application (or module) and classes that are loaded by classloaders that are ancestors of the
application (or module) classloader. This allows WebLogic Server to host multiple isolated
applications within the same JVM.
Application Classloader Hierarchy
WebLogic Server automatically creates a hierarchy of classloaders when an application is
deployed. The root classloader in this hierarchy loads any EJB JAR files in the application. A
child classloader is created for each Web application WAR file.
Because it is common for Web applications to call EJBs, the WebLogic Server application
classloader architecture allows JavaServer Page (JSP) files and servlets to see the EJB interfaces
in their parent classloader. This architecture also allows Web applications to be redeployed
without redeploying the EJB tier. In practice, it is more common to change JSP files and servlets
than to change the EJB tier.
The following graphic illustrates this WebLogic Server application classloading concept.
If your application includes servlets and JSPs that use EJBs:
.. Package the servlets and JSPs in a WAR file
.. Package the Enterprise JavaBeans in an EJB JAR file
.. Package the WAR and JAR files in an EAR file
.. Deploy the EAR file
Although you could deploy the WAR and JAR files separately, deploying them together in an
EAR file produces a classloader arrangement that allows the servlets and JSPs to find the EJB
classes. If you deploy the WAR and JAR files separately, WebLogic Server creates sibling
classloaders for them. This means that you must include the EJB home and remote interfaces in
the WAR file, and WebLogic Server must use the RMI stub and skeleton classes for EJB calls,
just as it does when EJB clients and implementation classes are in different JVMs. This concept
is discussed in more detail in the next section “Application Classloading and Pass-by-Value or
Reference” on page 4-14.
WebApp 2
EJB 3
Application 2
WebApp 3
WebLogic Server
System Classpath Loader
WebApp 1
EJB 1
Application 1
EJB 2
Note: The Web application classloader contains all classes for the Web application except for
the JSP class. The JSP class obtains its own classloader, which is a child of the Web
application classloader. This allows JSPs to be individually reloaded.