了解WebLogic Server应用程序类加载
Java 类加载
?
要对文件(相对于所展开应用程序的根)执行部分更新,请使用以下命令行:
java weblogic.Deployer -adminurl url -user user -password password
-name myapp -redeploy myejb/foo.class
在 -redeploy 命令后,提供要更新的文件(相对于已展开的应用程序的根)列表。这可能是特定元素(如上)或模块(或任何一组元素和模块)的路径。例如:
java weblogic.Deployer -adminurl url -user user -password password
-name myapp -redeploy mywar myejb/foo.class anotherejb
给定一组要更新的文件,系统将尝试计算重新部署所需要的最少内容。如果仅重新部署 EJB 实现类,则将仅重新部署该类。如果指定整个 EJB(在上例中为 anotherejb)或如果更改并更新 EJB Home 接口,则必须重新部署整个 EJB 模块。
该重新部署可能会导致其他模块也重新部署,具体取决于类加载器层次结构。特别是,如果其他模块共享 EJB 类加载器,或加载到该 EJB 的类加载器(如 WebLogic Server 标准类加载器模块中)的子类加载器中,则这些模块也将重新加载。
现代编程语言使用两种常见参数传递模型:“按值传递”和“按引用传递”。通过“按值传递”,将为每个方法调用复制参数和返回值。通过“按引用传递”,将向方法传递实际对象的指针(或引用)。因为“按引用传递”可以避免复制对象,所以它可以提高性能,但它也提供了修改被传递参数状态的一种方法。
WebLogic Server 中包含一种优化方法,能够提高服务器内远程方法接口 (RMI) 调用的性能。它不使用“按值传递”以及 RMI 子系统的编组和解组工具,而是由服务器通过“按引用传递”直接调用 Java 方法。此机制大大提高了性能,还可用于 EJB 2.0 本地接口。
RMI 调用优化和按引用调用仅适用于调用方和被调用方位于同一个应用程序内的情况。同样,这也与类加载器相关。由于应用程序具有自己的类加载器层次结构,任何应用程序类都会在两个类加载器中定义,如果您尝试在应用程序之间进行分配,则会引发 ClassCastException 错误。为解决这个问题,WebLogic Server 在应用程序之间使用“按值调用”,即使应用程序位于同一个 JVM 中,也会使用该方法。
在 WebLogic Server 中,系统类路径中的全部 .jar 文件由 WebLogic Server 系统类加载器加载。服务器实例中运行的所有应用程序都在应用程序类加载器(系统类加载器的子类加载器)中加载。在系统类加载器的此实现中,应用程序不能使用系统类加载器中已有的不同版本的第三方 jar。每个子类加载器都会要求父类加载器(系统类加载器)提供特定的类,但不能加载父类加载器所见的类。
例如,如果 $CLASSPATH
以及应用程序 EAR 中都包含名为 com.foo.Baz
的类,则将加载 $CLASSPATH
中的类,而不加载 EAR 中的类。由于 weblogic.jar
位于 $CLASSPATH
中,应用程序无法替代任何 WebLogic Server 类。
以下部分定义并介绍如何使用筛选类加载器:
FilteringClassLoader
提供一种机制,可用于对部署描述符进行配置,以明确指定:特定的包应始终从应用程序中加载,而不应由系统类加载器加载。这样,您可以使用其他版本的应用程序,例如 Xerces 和 Ant。
FilteringClassLoader
位于应用程序类加载器和系统之间。它是系统类加载器的子类加载器,也是应用程序类加载器的父类加载器。FilteringClassLoader
侦听 loadClass(String
className
)
方法,并将 className
与 weblogic-application.xml
文件中指定的一列包进行比较。如果该包匹配 className
,则 FilteringClassLoader
会引发 ClassNotFoundException
。该异常通知应用程序类加载器从应用程序中加载类。
要配置 FilteringClassLoader
,从而指定应从应用程序中加载特定的包,请向 weblogic-application.xml
文件中添加 prefer-application-packages
描述符元素,该文件详细列出要从应用程序中加载的包。下例指定 org.apache.log4j.* 和 antlr.* 包应从应用程序中加载,而不从系统加载器中加载:
<prefer-application-packages>
<package-name>org.apache.log4j.*</package-name>
<package-name>antlr.*</package-name>
</prefer-application-packages>
资源加载顺序是 java.lang.ClassLoader
的 getResource()
方法和 getResources()
方法返回资源的顺序。启用筛选时,该顺序与禁用筛选时的顺序稍有不同。启用筛选表示 FilteringClassLoader
中包含一个或多个包模式。不使用任何筛选(默认)时,将按照类加载器树的自上而下的顺序收集资源。例如,如果 Web (1) 请求资源,资源分组的顺序为:系统 (3)、应用程序 (2) 和 Web(1)。请参阅图 8-5。
系统 (3)
|
应用程序 (2)
|
Web (1)
为使说明更明确,给定一个资源 /META-INF/foo.xml
,它位于所有类加载器中且会返回下列 URL:
META-INF/foo.xml - from the System ClassLoader (3)
META-INF/foo.xml - from the App ClassLoader (2)
META-INF/foo.xml - from the Web ClassLoader (1)
启用筛选时,将返回从 FilteringClassLoader
(应用程序类加载器)的子类加载器到该调用类加载器中的资源,然后再返回系统类加载器中的资源。在图 8-6 中,如果同一资源位于所有类加载器 (D)、(B) 和 (A) 中,当 Web 类加载器请求该资源时,则将以如下顺序获得这些资源:
META-INF/foo.xml - from the App ClassLoader (B)
META-INF/foo.xml - from the Web ClassLoader (A)
META-INF/foo.xml - from the System ClassLoader (D)
FilteringClassLoader
下的默认 Java EE 委托模型。只将FilteringClassLoader
的父类加载器中的资源追加到所返回枚举值的末尾。 系统 (D)
|
FilteringClassLoader (filterList := x.y.*) (C)
|
应用程序 (B)
|
Web (A)
如果应用程序类加载器请求同一资源,将获得以下顺序。
META-INF/foo.xml - from the App ClassLoader (B)
META-INF/foo.xml - from the System ClassLoader (D)
getResource()
只返回第一个描述符,getResourceAsStream()
返回第一个资源的 inputStream
。
?
应用程序可能使用多个不同的 Java 类,包括企业 Bean、servlet、JavaServer Pages、实用程序类以及第三方包。WebLogic Server 通过不同的类加载器部署应用程序,从而维护独立性,并简化动态重新部署和取消部署。因此,您应以正确的方式打包应用程序类,以使每个模块都可以访问其所依赖的类。在某些情况下,可能必须在多个应用程序或模块中包含一组类。本部分描述 WebLogic Server 如何使用多个类加载器,以便您能够成功地临时保存应用程序。
现在每个资源适配器都使用其自己的类加载器加载类(类似 Web 应用程序)。结果,诸如 Web 应用程序和 EJB 等与应用程序归档(EAR 文件)中的资源适配器一起打包的模块无法访问资源适配器中的类。如果需要此类访问,则必须将资源适配器类放置在 APP-INF/classes 下。还可以归档这些类(使用 JAR 实用工具),并将它们放置在应用程序归档的 APP-INF/lib 下。
确保您的 WebLogic Server 系统类路径中不包含任何资源适配器特定的类。如果 Web 模块(例如,EJB 或 Web 应用程序)需要使用资源适配器特定的类,则您必须将这些类绑定在相应模块的归档文件(例如,EJB 的 JAR 文件或 Web 应用程序的 WAR 文件)中。
WebLogic Server在 EAR 文件提供了一个存储共享实用工具类的位置。将实用工具 JAR 文件放置在 APP-INF/lib 目录下,将各个类放置在 APP-INF/classes 目录下。(不要将 JAR 文件放置在 /classes 目录下,或将类放置在 /lib 目录下。)这些类将加载到应用程序的根类加载器中。
通过此功能,不必将实用工具类放置在系统类路径中,也不必将类放置在 EJB JAR 文件内 (取决于标准 WebLogic Server 类加载器层次结构)。请注意,使用此功能与使用前一部分所述的清单类路径稍有不同。使用此功能,可以在应用程序内共享类定义。而使用清单类路径,只是简单扩展了引用模块的类路径,这表明,每个模块都有各自的类副本。
Java EE 规范提供清单类路径条目,模块可以使用该方式指定其需要辅助类的 JAR。仅当您的 EJB JAR 或 WAR 文件中包含其他支持 JAR 文件时,才需使用清单类路径条目。在这种情况下,当您创建 JAR 或 WAR 文件时,您应包含清单文件,其中指明引用所需 JAR 文件的 Class-Path 元素。
下面是简单的清单文件,其中引用 utility.jar 文件:
Manifest-Version: 1.0 [CRLF]Class-Path: utility.jar [CRLF]
在清单文件的第一行,必须始终包含 Manifest-Version 特性,再另起一行 (CR | LF |CRLF),然后是 Class-Path 特性。有关清单格式的详细信息,请访问:http://java.sun.com/j2se/1.4/docs/guide/jar/jar.html#JAR
清单 Class-Path 条目指相对于对这些条目进行定义的当前归档的其他归档。该结构支持多个 WAR 文件和 EJB JAR 文件共享公用库 JAR。例如,如果 WAR 文件中包含的一个清单条目为 y.jar,该条目应位于 WAR 文件旁边(而不是在其中),如下:
<directory>/x.war
<directory>/y.jars
清单文件自身应位于 META-INF/MANIFEST.MF 下的归档中。
有关详细信息,请参阅 http://java.sun.com/docs/books/tutorial/jar/basics/manifest.html。
?
Java EE 库提供了一种简单方式,可以在多个企业应用程序之间共享一个或多个不同类型的 Java EE 模块。Java EE 库是已在部署时向 Java EE 应用程序容器注册的单个模块或一组模块。有关详细信息,请参阅创建共享 Java EE 库和可选包。
?
WebLogic Server 包含一个 lib
子目录,它位于域目录下,可以用于当服务器启动时向 WebLogic Server 系统类路径中添加一个或多个 JAR 文件。lib
子目录用于存放更改频繁的 JAR 文件,服务器中部署的所有或大多数应用程序或 WebLogic Server 本身都需要该子目录。例如,可以使用 lib
目录来存储域中所有部署都需要的第三方实用工具类。还可以使用它将修补程序应用到 WebLogic Server。
不建议将 lib
目录用于一般用途,例如,在域中部署的一个或两个应用程序之间共享 JAR,或共享需要定期更新的 JAR。如果更新 lib
目录中的 JAR,必须重新引导该域中的所有服务器,应用程序才能实现该更改。如果需要在若干应用程序之间共享 JAR 文件或 Java EE 模块,请使用创建共享 Java EE 库和可选包中描述的 Java EE 库功能。
要使用 lib
库共享 JAR,请执行下列操作:
lib
子目录中。例如:mkdir c:\bea\wlserver_10.0\samples\domains\wl_server\libcp c:\3rdpartyjars\utility.jar c:\bea\wlserver_10.0\samples\domains\wl_server\lib
lib
目录的权限。lib
目录下的文件复制到远程计算机上的受管服务器上。如果您的受管服务器的物理域目录与管理服务器的不同,则必须将 JAR 文件手工复制到受管服务器计算机的 domain_name
/lib
目录上。lib
目录中发现的 JAR 文件追回到系统类路径中。多个文件将按照字母顺序添加。from:http://middleware123.com/weblogic/docs100/programming/classloading.html