返回首页

JBossClassloader模型

时间:2009-12-16 00:56来源:未知 作者:admin 点击:
下图展示了一个包含EBJ模块和WAR模块时JBoss ClassLoader的一个结构。该结构没有使用偏平的JBoss ClassLoader,并且也没有画出在对EAR的Classloader进行隔离的时候JBoss类仓库的层次结构。 下面对这个图进行
  

下图展示了一个包含EBJ模块和WAR模块时JBoss ClassLoader的一个结构。该结构没有使用偏平的JBoss ClassLoader,并且也没有画出在对EAR的Classloader进行隔离的时候JBoss类仓库的层次结构。

下面对这个图进行说明:

  • System ClassLoaders: System ClassLoaders节点指向JVM主线程的thread context class loader (TCL)或者指向嵌入(内置)了JBoss server的应用程序thread context class loader。
  • ServerLoader:ServerLoader 节点指向一个委派给SystemClassLoaders的URLClassLoader,它是 org.jboss.system.server.NoAnnotationURLClassLoader实例,这个ClassLoader主要是 ServerLoader对象用来装载并运行Jboss Server实例所需要用到的一些类,它包含了下面的一些URL:
  • 所有通过在 系统属性jboss.boot.library.list指定的URL。该属性指定的路径是相对于jboss.lib.url属性指定路径的一个相对路 径。如果没有指定jboss.lib.url属性,它默认使用jboss.home.url + /lib/。如果没有指定boss.boot.library.list属性,它默认包含jaxp.jar,log4j-boot.jar, jboss-common.jar, 及jboss-system.jar。
  • JAXP JAR即可以是crimson.jar,也可以是xerces.jar,通过在Main的入口指定-j选择来确定最终使用哪一个,默认是crimson.jar。
  • JBoss JMX jar及GNU regex jar, jboss-jmx.jar和gnu-regexp.jar.
  • Oswego concurrency JAR, concurrent.jar
  • 通过命令行参数-L指定的所有jar包。
  • 其他的通过-C命令行参数指定的所有jar包或者目录。
  • Server:Server 是由org.jboss.system.server.Server接口实现创建的一个UCL。默认的实现是创建一个包含patchDir(它由 jboss.patch.url属性指定)和服务器conf目录的UCL。Server虽然有一个自己的ClassLoader,但它所有装载的类都放入 到UnifiedLoaderRepository3这个类仓库中。最后创建的UCL将被设置为JBoss main线程的Threadcontext ClassLoader。
  • All UnifiedClassLoader3s: All UnifiedClassLoader3节 点是由部署器创建的UCLs。它包括由部署描述器发现的EARs, jars, WARs,SARs及directories,它同时也包含那些在部署单元的jar包里通过manifests文件引用的jar包。它是一个扁平的 Classloader,因此不应该在不同的部署单里包含相同的jar包,如果包含了相同的jar包,只有第一个被载入的包会被使用,这也是并不是所期望 的结果。在Jboss有种机制来隔离EAR部署单元的Classloader可见性(通过在EAR包的META-INF/jboss-app.xml指 定<jboss-app>
    <loader-repository>some.dot.com:loader=webtest.ear</loader-repository>
    </jboss-app>来完成,这个方法可以将不同EAR里用到的包隔离起来)。采用这种机制你就可以在Jboss服务器里部署多个版本的Class。
  • EJB DynClassLoader: EJB DynClassLoader节点是一个URLClassLoader,它用来提供基于简单HTTP的WebService载入RMI动态类。它指定了一 个空的URL[],并将TCL作为它的父ClassLoader进行委派。如果WebService配置了允许系统级的类载入,则所有的在 UnifiedLoaderRepository3仓库里的类及系统classpath指定的类都可以通过HTTP载入。
  • EJB ENCLoader: EJB ENCLoader 节点是一个URLClassLoader,它仅有的作用是为EJB部署java:comp JNDI提供一个唯一的上下文。它指定了一个空的URL[],并且将EJB DynClassLoader作为它的父类进行委派。
  • Web ENCLoader: Web ENCLoader 节点是一个URLClassLoader,它仅有的作用也是为web部署提供一个唯一的java:comp JNDI上下文。它指定了一个空的URL[],并且将TCL作为它的父类进行委派。
  • WAR Loader: WAR Loader是 一个servlet容器特定的classloader,它将 WebENCLoader作为它的父类进行委派。它默认的行为是首先从父Classloader进行类载入,然后是WEB-INF/classes,最后 是WEB-IN/lib目录。如果Sevlet2.3的类装载模型enabled,则它将首先从它的WEB-INF目录进行装载,然后再是它的父 Classloader。

在现有的Jboss类装载结构中,有一些好处也有一些坏处。

好处包括:

  • 共享的类不再需要重复的在各个部署单元都存在。
  • 许多特性的实事变得可能,包括依赖或者冲突检测等。

坏处包括:

  • 已存在的部署可能需要重新打包来避免类重复。载入到仓库里的重复的类可能产生cast exceptions和linkage errors,这取决于怎么载入类。
  • 部署如果依赖于不同版本的class,则需要通过EAR的jboss-app.xml 描述文件进行隔离,使EAR使用独立的HeirarchicalLoaderRepository3来载入类。

JBoss启动和ClassLoader的关系:

下图简单的描述了JBoss启动过程和ClassLoader结构之间的简单关系:

  • Main: JBoss在执行org.jboss.Main的main()方法前由JVM创建了SystemClassLoader,并且当前TCL(Thread Context ClassLoader)为SystemClassLoader。
      1. JBoss的main方法创建一个名叫"JBoss"线程组,然后创建一个属于该线程组的线程,在线程中执行boot方法。
      2. boot方法首先处理main函数中的参数(及一些其他系统环境设置),接着用系统属性创建org.jboss.system.server.ServerLoader实例[new ServerLoader(props),其中props为系统属性]
      3. 在实例化ServerLoader后,main方法还为ServerLoader实例初始化一些附加的类库。
      4. 在初化完成后,调用ServerLoader上的load(ClassLoader)方法,传入的ClassLoader是当前线程的TCL(SystemClassLoader),取得Server实例。
      5. 然后调用Server实例上的server.init(props),并传入系统属性作为初始化参数。
      6. 在完成Server实例的初始化后,调用Server实例上的start方法,启动JBoss Server。

main大致的执行序列图如下:

在这里需要注意的,这些被main方法调用的方法,它们执行的TCL都是SystemClassLoader,而不管这些方法是ServerLoader实例上的还是Server实例上的。在被调用的方法返回前,被调用方法保证将TCL还原为调用前的那个TCL。

  • ServerLoader:ServerLoader的主要目的在于创建 NoAnotationURLClassLoader,并实例化具体的JBossserver对象。它的启动逻辑主要是在Main类调用 ServerLoader上的load方法时触发的。ServerLoader在执行load方法时,将顺序执行如下的逻辑:
      1. 根 据Main类在ServerLoader注册的类路径及jboss.boot.library.list指定的类路径或默认的jar包(参见上一节)创建 一个URLClassLoader(NoAnotationURLClassLoader实例),并设置方法的传入参数classLoader为新建 ClassLoader的父ClassLoader
      2. 方法通过系统属性jboss.server.type取得的类org.jboss.system.server.Server的实现类。如果没有取到,则默认使用org.jboss.system.server.ServerImpl
      3. 通 过新建的URLClassLoader(NoAnotationURLClassLoader实例)载入Server实现类,并用默认的构造器构造一个实 例。在载入Server实现类前,设置当前线程的TCL为新建的URLClassLoader(NoAnotationURLClassLoader), 在加载完成后,还原为加载前的TCL(SystemClassLoader)。
      4. 将得到的Server实例返回给调用者。这里指的是Main类里的load方法。
  • Server:Server是JBoss服务启动的核心部署,它初始化JBoss服务器相关的核心组件,并完成最终的应用部署。Main类的boot方法通过ServerLoader.load方法得到Server实例后,调用server实例上的server.init(props)方 法来初始化server实例。server.init在进行实例的初始化前,将当前线程的TCL设置成为载入Server实现类的那个 ClassLoader,通过情况下是NoAnotationURLClassLoader,设置完成后执行真正的初始化工作,这也使初始化的代码在 NoAnotationURLClassLoader环境里执行。在初始化完成后,方法将返回TCL为原先的那个 TCL(SystemClassLoader)。Main方法在完成server方法上的init方法后,接着调用server实例上的start方 法,start方法顺序的执行如下逻辑:
  1. 将当前线程的TCL设置为载入Server接口实现类的ClassLoader。同init方法,在这里是NoAntationURLClassLoader。使start方法运行在NoAntationURLClassLoader的环境中。
  2. 通过MBeanServiceFactory.createMBeanServer(String)方法创建MBeanServer实例。
  3. 在MBeanServer注册ServerImpl及ServerConfigImpl两个MBean。
  4. 根据patchUrl、Server对应的conf目录创建Server对应的UCL(UnifiedClassLoader)及相关的仓库(UnifiedLoaderRepository3)。并设置当前线程的TCL为新建的UCL。
  5. 创建org.jboss.system.ServiceController的MBean实例。ServiceController管理JBoss MBean服务的生命周期。
  6. org.jboss.deployment.MainDeployer 实例被创建并启动。MainDeployer管理部署依赖及将检查到的部署单元委派给相应的Deployer进行部署。参见:http://blog.csdn.net/youfly/archive/2009/02/12/3884062.aspx
  7. org.jboss.deployment. JARDeployer实例被创建并启动。JARDeployer处理jar的部署。参见:http://blog.csdn.net/youfly/archive/2009/02/12/3884062.aspx
  8. mainDeployer对定义在conf/jboss-service.xml文件里的MBean Service进行部署。在start方法完成返回前,还原TCL为调用start方法前的ClassLoader(SystemClassLoader)。

转载出处:www.jfuns.com www.jfuns.cn http://blog.csdn.net/youfly

顶一下
(4)
100%
踩一下
(0)
0%
------分隔线----------------------------
最新评论 查看所有评论
发表评论 查看所有评论
请自觉遵守互联网相关的政策法规,严禁发布色情、暴力、反动的言论。
评价:
表情:
用户名: 密码: 验证码:
发布者资料
小朱 查看详细资料 发送留言 加为好友 用户等级:超级会员 注册时间:2008-11-18 17:11 最后登录:2012-09-01 20:09
推荐内容
热点内容