WebSphere 中类加载器层次结构

Java 应用程序运行时,在 class 执行和被访问之前,它必须通过类加载器加载使之有效,类加载器是 JVM 代码的一部分,负责在 JVM 虚拟机中查找和加载所有的 Java 类和本地的 lib 库。类加载器的不同配置影响到应用程序部署到应用程序服务器上运行时的行为。JVM 和 WebSphere 应用程序服务器提供了多种不同的类加载器配置, 形成一个具有父子关系的分层结构。WebSphere 中类加载器的层次结构图 1 所示:


图1:
 

如上图所示,WebSphere 中类加载器被组织成一个自上而下的层次结构,最上层是系统的运行环境 JVM,最下层是具体的应用程序,上下层之间形成父子关系。

  • JVM Class loader:位于整个层次结构的最上层,它是整个类加载器层次结构的根,因此它没有父类加载器。这个类加载器负责加载 JVM 类, JVM 扩展类,以及定义在 classpath 环境变量上的所有的 Java 类。
  • WebSphere Extensions Class loader:WebSphere 扩展类加载器 , 它将加载 WebSphere 的一些 runtime 类,资源适配器类等。
  • WebSphere lib/app Class loader:WebSphere 服务器类加载器,它将加载 WebSphere 安装目录下 $(WAS_HOME)/lib/app 路径上的类。 在 WAS v4 版本中,WAS 使用这个路径在所有的应用程序之间共享 jar 包。从 WAS v5 开始, 共享库功能提供了一种更好的方式,因此,这个类加载器主要用于一些原有的系统的兼容。
  • WebSphere "server" Class loader:WebSphere 应用服务器类加载器。 它定义在这个服务器上的所有的应用程序之间共享的类。WAS v5 中有了共享库的概念之后,可以为应用服务器定义多个与共享库相关联的类加载器,他们按照定义的先后顺序形成父子关系。
  • Application Module Class Loader:应用程序类加载器,位于层次结构的最后一层,用于加载 J2EE 应用程序。根据应用程序的类加载策略的不同,还可以为 Web 模块定义自己的类加载器。

关于 WebSphere 的类加载器的层次结构,以下的几点说明可能更有助于进一步的理解类的查找和加载过程:

  • 每个类加载器负责在自身定义的类路径上进行查找和加载类。
  • 一个子类加载器能够委托它的父类加载器查找和加载类,一个加载类的请求会从子类加载器发送到父类加载器,但是从来不会从父类加载器发送到子类加载器。
  • 一旦一个类被成功加载,JVM 会缓存这个类直至其生命周期结束,并把它和相应的类加载器关联在一起,这意味着不同的类加载器可以加载相同名字的类。
  • 如果一个加载的类依赖于另一个或一些类,那么这些被依赖的类必须存在于这个类的类加载器查找路径上,或者父类加载器查找路径上。
  • 如果一个类加载器以及它所有的父类加载器都无法找到所需的类,系统就会抛出 ClassNotFoundExecption 异常或者 NoClassDefFoundError 的错误。

类加载器的委托模式

类加载器有一个重要的属性:委托模式(Delegation Mode,有时也称为加载方式:Classloader mode)。委托模式决定了类加载器在查找一个类的时候, 是先查找类加载器自身指定的类路径还是先查找父类加载器上的类路径。

类加载器的委托模式有两个取值:

  • Parent_First:在加载类的时候,在从类加载器自身的类路径上查找加载类之前,首先尝试在父类加载器的类路径上查找和加载类。
  • Parent_Last:在加载类的时候,首先尝试从自己的类路径上查找加载类,在找不到的情况下,再尝试父类加载器类路径。

有了委托模式的概念,我们可以更加灵活的配置在类加载器的层次结构中类的加载和查找方式。表 1 中给出了在 WebSphere 的类加载器层次结构中各个类加载器的委托模式的定义,并给出了不同的类加载器内类的生命周期。


 

注意:在上表中,"JVM Class loader" 因为在类加载器的最顶层,它没有父类加载器,因此其委托模式为 N/A,"WebSphere Extensions Class loader"和"WebSphere lib/app Class loader"的委托模式固定为表中的取值,不可配置,其它的类加载器的委托模式都是可以配置的。

WebSphere 中的类加载器策略

WebSphere 中对类加载器有一些相关的配置,称为类加载器策略(class loader policy)。类加载器策略指类加载器的独立策略(class loader isolation policy), 通过类加载器策略设置,我们可以为 WAS 和应用程序的类加载器进行独立定义。

每个 WAS 可以配置自己的应用程序类加载器策略,WAS 中的每个应用程序也可以配置自己的 Web 模块类加载器策略,下面我们对这两种策略分别介绍。

1 .应用服务器(WAS)配置:应用程序类加载器策略

应用服务器对应用程序类加载器策略有两种配置:

  • Single:整个应用服务器上的所有应用程序使用同一个类加载器。在这种配置下,每个应用程序不再有自己的类加载器。
  • Multiple:应用服务器上的每个应用程序使用自己的类加载器。

2 .应用程序配置:Web 模块类加载器策略

应用程序中对 Web 模块类加载器有两种配置:

  • Application:整个应用程序内的所有的实用程序 jar 包和 Web 模块使用同一个类加载器。
  • Module:应用程序内的每个 Web 模块使用自己的类加载器。应用程序的类加载器仍然存在,负责加载应用程序中 Web 模块以外的其它类,包括所有的实用程序 jar 包。

从上面的定义可以看出,不同的类加载器策略的配置下,类加载器的层次结构上的某些类加载器可能不存在。比如在应用程序服务器的应用程序类加载器策略定义为 single 的情况下,应用程序的类加载器将不存在,同一个应用服务器上的所有应用程序将共用同一个类加载器,这也就意味着不同的应用程序之间的类是共享的,应用程序间不能存在同名的类。

 

摘抄自:《如何在 WebSphere 中解决 jar 包冲突

Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐