Jboss AS7 类加载机制

  "Jboss AS7 类加载机制"

Posted by     "华恒" on Thursday, January 15, 2015

TOC

相对于Jboss之前的版本,AS7的类加载机制完全不同,AS7的类加载是基于JBoss模块来设计,关于JBoss模块的介绍,可以看上一篇文章Jboss模块介绍

隐式模块依赖

当你部署一个应用到Jboss容器的时候,有些依赖是隐式被加载的,例如如果部署一个Java EE的应用,包含EJBs,因为EJBs需要用到Javax.ejb.* 的包和其他一些Java EE API 相关包,包含这些包的Jar已经预先被制作成Module并且默认包含在容器里头作为JBoss AS的一部分,那么这些Jar的模块将会被自动加载。

那么隐式模块依赖是什么时候被加载的呢?当一个应用部署到容器里头,会经过一条叫做“deployment processors”的链。这条链上的每个processor都有方法去检测这个应用是否需要隐式加载一些模块,如果是,就将相关的依赖加载进来。

检测手段可以有多种,譬如Annotation。如果一个类添加了@Stateless声明,那么容器就知道,这是一个EJB的类。

Jboss AS7隐式加载的模块列表看这里:隐式加载的模块

类加载的优先级

类加载的先后顺序是为了避免类冲突,以下顺序按优先级从高到低排列:

  1. 系统依赖 - 就是上面说的隐式依赖。
  2. 用户依赖 - jboss-deployment-structure.xml里头定义的依赖;Manifest文件里通过Dependencies定义的依赖;Class-Path定义的依赖都属于用户依赖。
  3. 本地资源 - 就是打包在应用里头的类,包括WEB-INF/classes底下的类文件,WEB-INF/lib底下的Jar包
  4. 内部部署依赖 - 一个部署依赖于另一个部署;譬如一个EAR依赖另一个应用部署,EAR包lib底下的类等。

WAR包的类加载

一个WAR包作为一个单独的module,因此一个WAR包对应一个单独的class loader。

EAR包的类加载

EAR被看作为多module的部署。一般来说,EAR/lib这个文件夹会作为一个module,每一个WAR 或者EJB Jar包作为一个独立的module看待。子模块(WARs和EJB-Jars)一般来说会依赖父模块(EAR/lib),因此子模块可以访问EAR/lib底下的Jar,但子模块之间就不一定可见。可以通过ear-subdeployments-isolated来设置可见性。

<subsystem xmlns="urn:jboss:domain:ee:1.0" >            
  <ear-subdeployments-isolated>false</ear-subdeployments-isolated>
</subsystem>

默认值是false的,因此一个子模块可以访问另一个子模块的类。

譬如有下面的EAR包结构:

myapp.ear
 |
 |--- web.war
 |
 |--- ejb1.jar
 |
 |--- ejb2.jar

如果ear-subdeployments-isolated设置为false,那么web.war就可以访问ejb1.jar或者ejb2.jar里面的类,同理,ejb1.jar 跟ejb2.jar也是相互可见的。但是这个参数对具有单独类加载器的子部署是不生效的,譬如说EAR中的WAR包,因为每个WAR包是一个字部署,拥有独立的类加载器,因此WAR包之间的类是不可见的。同理,EAR底下Jar包的类也不能访问WAR包里的类。