码迷,mamicode.com
首页 > 其他好文 > 详细

classloader

时间:2016-06-22 23:39:39      阅读:478      评论:0      收藏:0      [点我收藏+]

标签:

4 Jboss 启动及加载过程

详细参考: http://tech.it168.com/j/2007-06-27/200706271521984.shtml

1) org.jboss.Main.main(String[]) 为入口 .

2) main 函数创建一个名叫” jboss ”的线程组 , 然后创建一个属于该组的线程 , 在线程中执行 boot 方法 .

3) boot 方法首先处理 main 函数中的参数 ( 及一些其它的系统环境设置 ), 接着就用系统的属性创建了org.jboss.system.server.ServerLoader 实例 [new ServerLoader(props)].

4) ServerLoader 注册 Jboss 相关的类路径 , 包括 XML 解析器 , jboss-jmx.jar, concurrent.jar 及其它的一些额外的类路径 .

5) ServerLoader 通过 load(ClassLoader) 方法创建 Jboss Server 实例 . 参数 ClassLoader 是 ClassLoader parentCL = Thread.currentThread(). getContextClassLoader( ) 得到的当前线程的类加载器 . 创建的Server 实例是 org.jboss.system.server.Server 接口的实现 . load(ClassLoader) 方法的细节:

Ø 用 jar 包及在 ServerLoader 中注册的类路径创建一个 URLClassLoader 的实例 , 把传入的 ClassLoader作为该 URLClassLoader 的 parent.

Ø Server 接口的实现类由系统属性 jboss.server.type 决定 , 默认是 org.jboss.system.server.ServerImpl.

Ø URLClassLoader 通过无参构造函数加载 Server 接口实现的实例 . 在加载前把当前线程的类加载器置为该URLClassLoader, 在加载完成后再置回之前传入的 ClassLoader.

6) Server 实例用系统属性进行初始化 [server.init(props)].

7) 服务起动 [server.start()]. 起动过程的默认实现如下 :

Ø 把当前线程类型加载器置为加载该 Server 接口实现实例的 ClassLoader.

Ø 在 jboss 域内 , 通过 MBeanServerFactory 的 createMBeanServer(String) 方法创建 MbeanServer 实例 .

Ø 在 MBean Server 上注册 ServerImpl 和 ServerConfigImpl 两个 MBean.

Ø 初始化统一的类加载仓库 (unified class loader repository), 用来装载服务器配置目录及其它可选目录下的jar 文件 . 对于每一个 jar 文件和类目录都会创建一个相应的 org.jboss.jmx.loading.UnifiedClassLoader实例 , 并且注册到统一的仓库中 . 其中一个 UnifiedClassLoader 实例会被设置为当前线程上下文的ClassLoader. [?: This effectively makes allUnifiedClassLoaders available through the thread context class loader.]

Ø 接下来创建 org.jboss.system.ServiceController 的 MBean 实例 . ServiceController 管理 JBoss MBean服务的生命周期 .

 http://www.cnblogs.com/svennee/p/4075514.html

 

 

Classloader 类加载器,用来加载 Java 类到 Java 虚拟机中。与普通程序不同的是。Java程序(class文件)并不是本地的可执行程序。当运行Java程序时,首先运行JVM(Java 虚拟机),然后再把Java class加载到JVM里头运行,负责加载Java class的这部分就叫做Class Loader。

JVM本身包含了一个ClassLoader称为Bootstrap ClassLoader,和JVM一样,BootstrapClassLoader是用 本地代码实现的,它负责加载核心JavaClass(即所有java.*开头的类)。另外JVM还会提供两个ClassLoader,它们都是用Java语言编写的,由BootstrapClassLoader加载;其中Extension ClassLoader负责加载扩展的Javaclass(例如所有javax.*开头的类和存放在JRE的ext目录下的类),ApplicationClassLoader负责加载应用程序自身的类。

当运行一个 程序的时候,JVM启动,运行bootstrapclassloader,该ClassLoader加载java核心API(ExtClassLoader和AppClassLoader也在此时被加载),然后调用ExtClassLoader加载扩展API,最后AppClassLoader加载CLASSPATH目录下定义的Class,这就是一个程序最基本的加载流程。

注: 学ClassLoader看OSGI程序应用

什么时候JVM会使用ClassLoader加载一个类呢?当你使用java去执行一个类,JVM使用ApplicationClassLoader加载这个类;然后如果类A引用了类B,不管是直接引用还是用Class.forName()引用,JVM就会找到加载类A的ClassLoader,并用这个ClassLoader来加载类B。JVM按照运行时的有效执行语句,来决定是否需要装载新类,从而装载尽可能少的类,这一点和编译类是不相同的。

Why use your own ClassLoader?

似乎JVM自身的ClassLoader已经足够了,为什么我们还需要创建自己的ClassLoader呢?

因为JVM自带的ClassLoader只是懂得从本地文件系统加载标准的java class文件,如果编写你自己的ClassLoader,你可以做到:

1)在执行非置信 代码之前,自动验证数字签名

2)动态地创建符合用户特定需要的定制化构建类

3)从特定的场所取得java class,例如数据库中

4) 等等

事实上当使用Applet的时候,就用到了特定的ClassLoader,因为这时需要从网络上加载java class,并且要检查相关的安全信息。

应用服务器大都使用了ClassLoader技术,即使你不需要创建自己的ClassLoader,了解其原理也有助于更好地部署自己的应用。

classloader - 树状结构

当你决定创建你自己的ClassLoader时,需要继承java.lang.ClassLoader或者它的子类。在实例化每个ClassLoader对象时,需要指定一个父对象;如果没有指定的话,系统自动指定ClassLoader.getSystemClassLoader()为父对象。

所以当创建自己的Class Loader时,只需要 重载findClass()这个方法。

classloader - 卸载重载

当一个javaclass被加载到JVM之后,它有没有可能被卸载呢?我们知道Win32有FreeLibrary()函数,Posix有 dlclose()函数可以被调用来卸载指定的 动态连接库,但是Java并没有提供一个UnloadClass()的方法来卸载指定的类。

在Java中,java class的卸载仅仅是一种对系统的优化,有助于减少应用对内存的占用。既然是一种优化方法,那么就完全是JVM自行决定如何实现,对Java开发人员来说是完全透明的。

在什么时候一个java class/interface会被 卸载呢?Sun公司的原话是这么说的:"class or interfacemay be unloaded if and only if its class loader is unreachable. Classesloaded by the bootstrap loader may not be unloaded."

事实上我们关心的不是如何卸载类的,我们关心的是如何更新已经被加载了的类从而更新应用的功能。JSP则是一个非常典型的例子,如果一个JSP文件被更改了, 应用服务器则需要把更改后的JSP重新编译,然后加载新生成的类来响应后继的请求。

其实一个已经加载的类是无法被更新的,如果你试图用同一个ClassLoader再次加载同一个类,就会得到异常(java.lang.LinkageError: duplicate classdefinition),我们只能够重新创建一个新的ClassLoader实例来再次加载新类。至于原来已经加载的类,开发人员不必去管它,因为它可能还有实例正在被使用,只要相关的实例都被内存回收了,那么JVM就会在适当的时候把不会再使用的类卸载。

使用 线程上下文类加载器, 可以在执行线程中, 抛弃双亲委派加载链模式, 使用线程上下文里的类加载器加载类.

典型的例子有, 通过 线程上下文来加载第三方库jndi实现, 而不依赖于双亲委派.

大部分java app服务器(jboss, tomcat..)也是采用contextClassLoader来处理web服务。

当然, 好东西都有利弊. 使用 线程上下文加载类, 也要注意, 保证多根需要通信的线程间的类加载器应该是同一个, 防止因为不同的类加载器, 导致类型转换异常(ClassCastException).

参考资料及图片来源——Understanding J2EE Application Server Class Loading Architectures

http://www.baike.com/wiki/classloader

如图所示:

技术分享

classpath对应的JVM中的类和jboss-home/lib目录下的类处于最底层,我们暂且称之为“低级”层;

deploy目录中应用中的类和server/xxx/lib中的类处于中间层,称之为“中级”层;

WAR包中的类处于最高级,称之为“高级”层;

jboss的类加载机制为高级层中的类可以应用中低级层中的类,中级层中的类可以引用低级层中的类,反之则不行。即处于上层中的类对于处于下层中的类是不可见的。

此种类加载机制可以让我们在发布的多个应用程序共享类包。但是也有其缺点:如果两个application需要同一个类包的不同版本,这种方式无法解决了。可以通过配置范围来解决。

http://blog.csdn.net/daydaylearn/article/details/7949186

1.  概念介绍

UCL : org.jboss.mx.loading.UnifiedClassLoader3 ,它继承标准的java.net.URLClassLoader,覆盖了标准parent delegation模型以使用共享class和资源仓库

 

仓库(responsitory): org.jboss.mx.loading.UnifiedLoaderRepository3。

 

平面模型:为了热deploy模块的需要,JBoss实现了自己的类装载器UnifiedClassLoader3,一般来说,一个顶层的deployment就有一个UnifiedClassLoader3实例为之工作。一个deployment所装载的类,其他 deployment是可见的。全局唯一的UnifiedLoaderRepository3实例用于管理这些类,以及装载它们的UnifiedClassLoader3。UnifiedLoaderRepository3实例和UnifiedClassLoader3实例是一对多的关系。

2. jboss classloader机制
   

技术分享<mbean code="org.jboss.management.j2ee.LocalJBossServerDomain"
技术分享      name="jboss.management.local:j2eeType=J2EEDomain,name=Manager">
技术分享      <attribute name="MainDeployer">jboss.system:service=MainDeployer</attribute>
技术分享      <attribute name="SARDeployer">jboss.system:service=ServiceDeployer</attribute>
技术分享      <attribute name="EARDeployer">jboss.j2ee:service=EARDeployer</attribute>
技术分享      <attribute name="EJBDeployer">jboss.ejb:service=EJBDeployer</attribute>
技术分享      <attribute name="RARDeployer">jboss.jca:service=RARDeployer</attribute>
技术分享      <attribute name="CMDeployer">jboss.jca:service=ConnectionFactoryDeployer</attribute>
技术分享      <attribute name="WARDeployer">jboss.web:service=WebServer</attribute>
技术分享      <attribute name="CARDeployer">jboss.j2ee:service=ClientDeployer</attribute>
技术分享      <attribute name="MailService">jboss:service=Mail</attribute>
技术分享      <attribute name="JMSService">jboss.mq:service=DestinationManager</attribute>
技术分享      <attribute name="JNDIService">jboss:service=Naming</attribute>
技术分享      <attribute name="JTAService">jboss:service=TransactionManager</attribute>
技术分享      <attribute name="UserTransactionService">jboss:service=ClientUserTransaction</attribute>
技术分享      <attribute name="RMI_IIOPService">jboss:service=CorbaORB</attribute>
技术分享   </mbean>


   首先看一下各种类型的deployer。不同的deployer是根据文件的后缀进行区分。MainDeployer起到一个controller的作用,根据不用的后缀分发到不同的deployer进行处理。如果是*.ear,则会由EARDeployer进行载入。
应用的加载时一个 Top Level Deployer + Top Level Ucl。 举个例子,比如发布一个a.ear应用,ear应用中会包含一个*.war。这时候就会涉及deployer选择问题。jboss采取的原则就是按Top Level,根据最顶层的应用选择deployer,继而也有了top level ucl的概念。由顶级的ucl来加载整个应用。这里需要注意的是war的部署有点特别。它只是将自身添加到ucl的classpath域中,而war下的WEB-INF/lib/*.jar,则是由WebAppClassloader来加载。可调整ear下的 META-INF/jboss-service.xml中的UseJbossWebLoader属性。如果设置为true,故名思义就是用ucl来加载war下的jar包。否则就是采用独立的classloader加载。
   再看一下ucl的加载过程,首先会调用仓库去loadclass,仓库在查找无果的情况下会回调各自的UCL去加载本地库。
技术分享

3. jboss scope配置

ClassLoadingConfiguration一书中描述:

There are two levels of scoping, isolation from other deployments, and isolation that overrides the loading of JBoss server classes. With nested modules, only the top level file may specify class loader scoping. If you have a .ear file containing other modules, only scoping specified in the .ear ‘s META-INF/jboss-app.xml is used. This also applies for any other deployment which contains sub-deployments. For example, if a .sar contains a .war deployment, only the .sar META-INF/jboss-service.xml scoping has effect.

 

   意思是说,scope配置只能是顶级下的配置,比如一个.sar中包含.war都配置了scope,只有.sar下的 META-INF/jboos-service.xml才有效。这也与前面 TOP level UCL + TOP Devloper相对应。
    

    针对.sar,你可以在jboss-service.xml中,添加如下配置:

技术分享<server>  
技术分享    <loader-repository> com.example:loader=unique-archive-name </loader-repository>  
技术分享</server>


        
    针对.ear,你可以在jboss-app.xml添加如下配置:
    

技术分享<jboss-app>  
技术分享  <loader-repository>com.example:loader=unique-archive-name</loader-repository>  
技术分享</jboss-app>

    
    针对 .war,你可以在jboss-web.xml添加如下配置:
    

技术分享<jboss-web>
技术分享<class-loading java2ClassLoadingCompliance=‘true‘>  
技术分享       <loader-repository>    
技术分享             com.example:loader=unique-archive-name  
技术分享             <loader-repository-config>  
技术分享                 java2ParentDelegaton=true  
技术分享             </loader-repository-config>  
技术分享      </loader-repository>    
技术分享 </class-loading>
技术分享</jboss-web>

   
   注意,在最新的4.2.1版本中,<class-loading>标签已经不再使用,你可以直接配置:

技术分享<jboss-web>    
技术分享    <loader-repository> com.example:loader=unique-archive-name </loader-repository>    
技术分享</jboss-web>


    针对这两种方式的配置,4.0.5版本都支持。  
      
    针对典型的ear+war应用,*.ear/META-INF/jboos-service.xml,用于调整war的加载方式。
 

技术分享<!-- Get the flag indicating if the normal Java2 parent first class   
技术分享           loading model should be used over the servlet 2.3 web container first   
技术分享           model.   
技术分享      -->  
技术分享      <attribute name="Java2ClassLoadingCompliance">false</attribute>  
技术分享      <!-- A flag indicating if the JBoss Loader should be used. This loader   
技术分享           uses a unified class loader as the class loader rather than the tomcat   
技术分享           specific class loader.   
技术分享           The default is false to ensure that wars have isolated class loading   
技术分享           for duplicate jars and jsp files.   
技术分享      -->  
技术分享      <attribute name="UseJBossWebLoader">false</attribute>  
技术分享

    配置java2ClassLoadingCompliance为true,则表明是选择parent first。典型的classloader的双亲委托模型,否则是采用child first,先从自身加载,找不到再相父类请求。
    配置UseJBossWebLoader为false,则webapp的加载通过独立于jboss的classloader进行加载。

http://agapple.iteye.com/blog/791940

 

原文:http://blog.csdn.net/youfly/archive/2009/02/12/3884062.aspx

 

部署器(Deployers) 是一种将组件整合进JBoss服务器的一种机制,部署器同时也是大多数的UCL实例的创建者,MainDeployer是主要的创建者。 MainDeployer通过init方法在部署的初期创建UCL。UCL是通过调用 DeploymentInfo.createClassLoaders()方法来创建的。只有最高层的DeploymentInfo(每一种部署组件都有 对应的DeploymentInfo)才进行实际的UCL创建工作。其他的子部署(subdeployments)将设置他们的classpath到父 DeploymentInfo创建的UCL中。每个部署都有一个独立的URLClassLoader,并且该部署将自身的部署url作为 classpath的一部分添加到这个ClassLoader中,这主要是用作载入本地资源如部署描述符等信息。下图提供了一个图例说明了 Deployers,DeploymentInfos,Classloaders的交互过程。

技术分享

这个图说明了一个包含EJB及WAR子部署的EAR部署过程。EJB的部署通过引用了lib/util.jar工具包。WAR在它的WEB- INF/classes包含了java类,在它的WEB-INF/lib/目录里包含了jbosstest-web-util.jar包。每一个部署都有 它们自己的DeploymentInfo实例,并且有一个URLClassLoader指它他们的部署包。和some.ear关联的 DeploymentInfo仅有一个UCL被创建。ejbs.jar和web.war DeploymentInfos将添加它们的部署包到some.ear UCL的classpath中。并且共享这个UCL作为它们的部署UCL。EJBDeployer同时也会添加在manifestf里引用的jar到 EAR的UCL中。

WARDeployer的行为和别的部署器有些不同,它仅仅添加了它的WAR包到它的DeploymentInfo UCL的classpath中。WAR包里的WEB-INF/classes和WEB-INF/lib目录将由Server容器的ClassLoader 来载入。servlet容器的class loader将WAR包的DeploymentInfo UCL作为它的父ClassLoader,并进行委派,但是servlet容器的class loader并不是boss class loader repository的一部份。因此,在WAR包里的类对于别的组件将是不可见的。如果需要将类在各个组件(如EJBs,MBeans)里进行共享,则需 要将类载入到共享的class loader repository中,而不管这些类是包含在SAR,EJB部署中,还是通过jar包的manifest文件里的Class-Path条目进行引用的共 享类。在SAR的情况下,在服务部署描述里的classpath元素和jar的manifest Class-Path具有相同的效果和目的。

http://blog.csdn.net/dknypxt/article/details/5671944

下图是JBoss class loading体系结构:

技术分享

上图是JBoss核心ClassLoader组件,它的核心部分是org.jboss.mx.loading.UnifiedClassLoader3(UCL)。 它继承标准的java.net.URLClassLoader,覆盖了标准parent delegation模型以使用共享class和资源仓库。这个共享的仓库是 org.jboss.mx.loading.UnifiedLoaderRepository3。 每一个UCL关联到单一的一个UnifiedLoaderRepository3 , 并且一个 UnifiedLoaderRepository3 通 常拥有多个UCL。一个UCL可能具有多个URL用来载入class和资源。部署器使用最顶层的部署单元UCL作为它的共享classloader,并且 所有的部署都关联的这个ClassLoader。

当一个UCL请求载入一个类时,它首先去它关联的仓库cache查找,看是否这个类已被 载入。仅当这个类在仓库里不存在时,它才由UCL载入到仓库中。通常的,所有UCL实例共享一个UnifiedLoaderRepository3。 这意味着UCL是一个扁平的ClassLoader。 

下面是UnfiedClassLoader3.loadClass(String, boolean)完整的执行序列:

    1. 检查UnifiedClassLoader3关联的 UnifiedLoaderRepository3 类 cache。如果类在cache找到,则返回这个类。

    2. 否则,检查UnfiedClassLoader3 是否能够载入这个类。它本质上调用了父类URLClassLoader.loadClass(String, boolean) 方法来查看这个类是否存在于当前ClassLoader关联的URL里,或者在当前ClassLoader的父 ClassLoader里。如果类被找到,则将它放到的仓库的Class cache里,并返回找到的类。

    3. 否 则,仓库根据包名到UCl的印射查询其他的UCL是否有能力载入这个类。当一一个UCL添加到仓库中时,将建立UCL载入类的包名到当前这个UCL的印射 关系。这就能够快速的确定哪一个UCL能够载入当前类。 然后UCLs根据每个UCL添加到仓库里时指的顺序请求载入指定的类。如果其中一个UCL能够找到这个类,则返回这个类,如果都不能找到,则抛出java.lang.ClassNotFoundException 异 常。

http://blog.csdn.net/dknypxt/article/details/5671947

 下图展示了一个包含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)。

http://blog.csdn.net/dknypxt/article/details/5671941

 

JBoss、Tomcat Classloader不完全分析

由于平时项目中用到的还是JBoss 4.2.x所以我这里的分析时针对这个版本的,不一定适用其他JBoss版本。 
下面言归正传。 
JBoss为了实现类的共享引入了class loader repository的概念,并且设计了org.jboss.mx.loading.UnifiedClassLoader3 (UCL)来完成sharing classes的主要功能。 
UCL和UnifiedLoaderRepository3 一对多的关系,默认情况下一个jboss实例中只有一个UnifiedLoaderRepository3实例,这个UnifiedLoaderRepository实例会和所有的UCL关联。 
NoAnnotationClassLoader是UCL的父classloader用来加载$JBOSS_HOME/lib下的jar,system class loader是NoAnnotationClassLoader的父classloader。 
这几个对象的关系请见下图 
技术分享 
从上图可以看出默认情况下所有的UCL共享一个Repository,通过Repository可以实现class的共享。UnifiedLoaderRepository3实例中维护着两个容器,一个是class cache:这个容器很明显缓存了一些class,这样可以提高loadClass方法的执行效率;另一个是packagesMap:这个map维护的是类的包名和UCL的mapping关系。具体UCL按什么逻辑load class的请看下面的活动图: 
技术分享 
UnifiedClassLoader3的继承结构如下图所示,UnifiedClassLoader3的父类RepositoryClassLoader重写了URLClassLoader的loadClass方法,实现了上图的逻辑 
技术分享 
下面请看一下相关代码: 
RepositoryClassLoader.java 

Java代码  技术分享
  1. public Class loadClass(String name, boolean resolve)  
  2.       throws ClassNotFoundException  
  3.    {  
  4.       boolean trace = log.isTraceEnabled();  
  5.       if (trace)  
  6.          log.trace("loadClass " + this + " name=" + name+", loadClassDepth="+loadClassDepth);  
  7.       Class clazz = null;  
  8.       try  
  9.       {  
  10.          if (repository != null)  
  11.          {  
  12.             clazz = repository.getCachedClass(name);//先从cache中load class  
  13.             if (clazz != null)  
  14.             {  
  15.                if( log.isTraceEnabled() )  
  16.                {  
  17.                   StringBuffer buffer = new StringBuffer("Loaded class from cache, ");  
  18.                   ClassToStringAction.toString(clazz, buffer);  
  19.                   log.trace(buffer.toString());  
  20.                }  
  21.                return clazz;  
  22.             }  
  23.          }  
  24.          //loadClassImpl中会调用的LoadMgr3的一些方法实现上面流程图的逻辑,具体的代码实现比较冗长,这里就不贴出来了  
  25.          clazz = loadClassImpl(name, resolve, Integer.MAX_VALUE);  
  26.          return clazz;  
  27.       }  
  28.       finally  
  29.       {  
  30.          if (trace)  
  31.          {  
  32.             if (clazz != null)  
  33.                log.trace("loadClass " + this + " name=" + name + " class=" + clazz + " cl=" + clazz.getClassLoader());  
  34.             else  
  35.                log.trace("loadClass " + this + " name=" + name + " not found");  
  36.          }  
  37.       }  
  38.    }  


有几点结论可以加深一些印象: 

  1. JBoss做为Application Server可以部署ear包也可以war包。但是jboss在默认情况下处理ear和war是两种class load机制。
  2. 当部署ear时,JBOSS默认使用我前面提到的class load机制。一个ear包里的所有的jar由一个UCL统一加载和管理
  3. 需要注意的是ear里的war的部署有点特别。它只是将自身添加到ucl的classpath域中,而war下的WEB-INF/lib/*.jar,则是由WebAppClassloader来加载


由于jboss对所有UCL的共享机制就会导致出现一些class的版本冲突问题,一些应用加载不到自己的应用需要的class。对于这个问题JBOSS提供了一些解决措施:http://community.jboss.org/wiki/ClassLoadingConfiguration。后面我会再整理一下此前我遇到过的一个class冲突的case和解决办法。 

Tomcat6/7 class loader机制 
Tomcat class loader层次结构 
技术分享
Tomcat的class load机制较Jboss来说要简单 
当web应用需要load class时先调用WebAppClassloader的loadClass方法,loadClass内部逻辑如下: 

  1. 调用findLoadedClass(String)检查此class是否已经加载,如果以加载则直接返回,如果没有则继续做下一步。
  2. 调用system class loader的loadClass的方法,这样可以加载到JDK核心的类,如果没有找到符合的类则继续做下一步。
  3. 如果WebAppClassloader的delegate属性是true或者正在处理的class在过滤列表里,会先从父class loader中加载类。如果没有则继续做下一步。一般这一步不会执行。
  4. WebAppClassloader在自己的类库(WEB-INF/classes和WEB-INF/lib)中查找class。如果没有则继续做下一步。
  5. 如果前面第3步已经跳过这一步会继续执行。如果前面第3步已经执行过,这一步就不会再执行。这一步的执行逻辑同第3步。


具体的代码可以看WebAppClassloader.loadClass(..) 

参考文档: 
http://community.jboss.org/wiki/JBossClassLoadingUseCases 
http://community.jboss.org/wiki/ClassLoadingConfiguration 
http://community.jboss.org/wiki/EnableClassloaderLogging 
http://agapple.iteye.com/blog/791940

 

http://seanhe.iteye.com/blog/841723

 

Discussion

 

By default JBoss (prior to version 3.2) uses a flat class loading model that avoids the need to redundantly include classes in different layers.  WAR files would only have the web contents and servlets, EJBs their interfaces, implementations and types, etc. Canonical packaging works correctly with this model.

 

However, if you have applications that cannot share classes because of version conflicts, then you need to isolate the classes from other deployments. Without isolation, common errors seen are ClassCastException, IllegalAccessErrors, VerifyErrors and in general, strange behavior that changes as new deployments are added and removed.

 

There are two levels of scoping, isolation from other deployments, and isolation that overrides the loading of JBoss server classes.  With nested modules, only the top level file may specify class loader scoping. If you have a .ear file containing other modules, only scoping specified in the .ear‘s META-INF/jboss-app.xml is used. This also applies for any other deployment which contains sub-deployments.  For example, if a .sar contains a .war deployment, only the .sar META-INF/jboss-service.xml scoping has effect.

 

Specifying Isolation

 

For .ear files, in your jboss-app.xml, add the following descriptor fragment construct to enable scoped class loading:

 

<jboss-app>
   <loader-repository> 
   com.example:archive=unique-archive-name 
   </loader-repository> 
</jboss-app>

 

 

For .war files, in your jboss-web.xml, the following template applies:

<jboss-web>
   <class-loading> 
      <loader-repository>com.example:archive=unique-archive-name</loader-repository> 
   </class-loading>
</jboss-web> 

 

 

Note for AS 4.2.x and versions till 5.x: As of at least JBoss 4.2.1, the <class-loading> tag appears to no longer be supported as isolation is ignored. Instead, the following configuration appears to accomplish the same goal:

 
<jboss-web>
   <loader-repository> 
      com.example:archive=unique-archive-name 
   </loader-repository> 
</jboss-web> 

Interestingly enough, 4.0.5 seems to support both configurations.*

 

 

For .sar files, in your jboss-service.xml, the following template applies:

<server>
     <loader-repository>
          com.example:archive=unique-archive-name 
     </loader-repository>
</server>

 

 

The <loader-repository> elements must be correctly placed within the respective

<jboss-app>, <jboss> and <jboss-web> XML elements.

Check the corresponding DTD found in the docs/dtd directory of the distribution for the complete content model.

 

Note for 5.x and later versions: The above mentioned configuration might still work with the 4.0.x till 5.x version due to their xsd/dtd, but for versions 5.x and above the old configuration still applies for jboss-web.xml:

 

 
  1. <jboss-web>  
  2.    <class-loading>   
  3.       <loader-repository>com.example:archive=unique-archive-name</loader-repository>   
  4.    </class-loading>  
  5. </jboss-web>  

 

The com.example:archive=unique-archive-name strings are JMX ObjectName

strings. These have no particular significance other than that they must be unique.

It might be useful to use the same name as used for the .ear, .war, or .sar file.

For example, for a petstore.ear file, use: com.example:loader=petstore.ear as the repository name.

 

The loader-repository ObjectName will appear in the JMX-Console (http://localhost:8080/jmx-console/).

This MBean is great for debugging any class-loading issues which might arise.

The hierarchical loaders created from the repository wll appear together under the loader-repository domain name,

com.example in the example.

 


 

 

Isolation with Overriding Server Classes

 

Use the following constructs to enabled scoped class loading with the deployment classes overriding the server classes.

 

For jboss-app.xml:

 

 
<jboss-app>
  <loader-repository> 
  com.example:archive=unique-archive-name 
     <loader-repository-config> 
     java2ParentDelegation=false 
     </loader-repository-config> 
  </loader-repository>
</jboss-app>

 

 

For jboss-web.xml:

<jboss-web>
   <class-loading java2ClassLoadingCompliance="false">
      <loader-repository>
         com.example:archive=unique-archive-name
         <loader-repository-config>java2ParentDelegation=false</loader-repository-config>
      </loader-repository>
   </class-loading>
 ...

Note: See comment above regarding web class loader isolation.

 

For jboss-service.xml:

<server>
   <loader-repository>
      com.example:archive=unique-archive-name
      <loader-repository-config>java2ParentDelegation=false</loader-repository-config>
   </loader-repository>
 ...

 

The isolated EAR or WAR repository will load its libraries in this order:

 

  1. WEB-INF/lib (for WARs)

  2. libraries in server/default/lib

  3. tomcat-libraries in server/default/deploy/jbossweb-tomcat50.sar (jboss-3.2.6).

 

The libraries in server/default/lib get mixed together with jbossweb-tomcat50.sar in no specific order (for details look into the loader-repository in the JMX-console).

 

The Web Container

 

In jboss-3.2.3, the jbossweb-tomcat41.sar is configured to use a unified class loader as the web application class loader. This is controlled by the UseJBossWebLoader attribute in the jbossweb-tomcat41.sar/META-INF/jboss-service.xml descriptor. The use of a unified class loader means that the classes available in the war inside of the WEB-INF/classes and WEB-INF/lib are incorporated into the default shared class loader repository. This may not be what you want as its contrary to the default servlet 2.3 class loading model and can result in sharing of classes/resources between web applications. You can disable this by setting this attribute to false.

 

The Web Container from 4.0.2

 

From 4.0.2 JBoss has changed to the Servlet spec classloading model, i.e. it uses the Tomcat classloader. See the related JIRA Task

 

Simplified Configuration from 3.2.4

 

From JBoss-3.2.4 the EAR deployer provides a simplified version of the isolation. You can configure all your ears to be in isolated classloader spaces using call by value for remote interfaces.

 

The EARDeployer is configured in conf/jboss-service.xml for versions 3.x and in deploy/ear-deployer.xml for versions 4.x+

 

 <!-- EAR deployer, remove if you are not using Web layers -->
 <mbean code="org.jboss.deployment.EARDeployer" name="jboss.j2ee:service=EARDeployer">

    <!-- Isolate all ears in their own classloader space -->
    <attribute name="Isolated">true</attribute>

    <!-- Enforce call by value to all remote interfaces -->
    <attribute name="CallByValue">true</attribute>
 </mbean>

 

Accessing EJBs in isolated ears

 

If you want to make JNDI lookups across EARs that are isolated, you need to force

marshalling of the lookup, e.g. if you have the following ejb-ref in your ejb-jar.xml

that references an EJB in an isolated EAR

 <?xml version="1.0" encoding="UTF-8"?>
 <!DOCTYPE ejb-jar PUBLIC
    "-//Sun Microsystems, Inc.//DTD Enterprise JavaBeans 2.0//EN"
    "http://java.sun.com/dtd/ejb-jar_2_0.dtd">

 <ejb-jar>
   <enterprise-beans>
     <session>
         <ejb-name>SessionA</ejb-name>
         <home>org.jboss.test.isolation.interfaces.a.SessionAHome</home>
         <remote>org.jboss.test.isolation.interfaces.a.SessionA</remote>
         <ejb-class>org.jboss.test.isolation.ejb.a.SessionAEJB</ejb-class>
         <session-type>Stateless</session-type>
         <transaction-type>Container</transaction-type>
         <ejb-ref>
            <ejb-ref-name>ejb/SessionB</ejb-ref-name>
            <ejb-ref-type>Session</ejb-ref-type>
            <home>org.jboss.test.isolation.interfaces.b.SessionBHome</home>
            <remote>org.jboss.test.isolation.interfaces.b.SessionB</remote>
         </ejb-ref>
     </session>
   </enterprise-beans>
 </ejb-jar>

 

In jboss.xml use the full scheme to define the lookup:

 <?xml version="1.0" encoding="UTF-8"?>

 <jboss>
    <enterprise-beans>
       <session>
         <ejb-name>SessionA</ejb-name>
         <ejb-ref>
            <ejb-ref-name>ejb/SessionB</ejb-ref-name>
            <jndi-name>jnp://${jboss.bind.address:localhost}:1099/SessionB</jndi-name>
         </ejb-ref>
      </session>
    </enterprise-beans>
 </jboss>

 

You can also use the full scheme in lookups from non-EJB clients such as standalone applications or JSP pages. In this case you would be encoding deployment knowledge into the code - the applications will always use call-by-value even if your needs change. If you are retro-fitting classloader isolation you may also have a lot of lookup code to change, although you should probably have used a constant or lookup service to hold the actual name.

 

An alternative is to force all JNDI lookups to be call-by-value, which you can do in

/deploy/naming-service.xml (This used to reference

/conf/jboss-service.xml, which is WRONG for 4.0.3) in the section headed JNDI. Change the jboss:service=Naming bean

definition so that the CallByValue attribute reads:

 

<mbean code="org.jboss.naming.NamingService"
      name="jboss:service=Naming"
      xmbean-dd="resource:xmdesc/NamingService-xmbean.xml">

  ...

  <attribute name="CallByValue">true</attribute>

  ...

</mbean>

 

This is indiscriminate - JBoss will be unable to optimise any JNDI calls any more, but may be appropriate in some circumstances.

 

Performance note - Call By Value

 

The use of call by value and marshalling is very inefficient. It typically means

method invocations take 10 times the cpu. Why? Compare Call By Value with Call By Reference

 

Call By Reference

  1. caller does ejb.someMethod()

  2. invocation is passed through ejb container

  3. container does bean.someMethod()

  4. result is returned to the caller

 

Call By Value

  1. caller does ejb.someMethod()

  2. invocation is marshalled - the parameters are turned into ObjectStream (a byte[])

  3. container with a different classloader unmarshalls - byte[] -> java Objects - including classloading

  4. invocation is passed through ejb container

  5. container does bean.someMethod()

  6. result is marshalled - the return value is turned into ObjectStream

  7. result is unmarshalled using the caller‘s classloader - byte[] -> java Object

  8. result is return to the caller

 

The marshalling and unmarshalling uses a lot of cpu.

 

Related

JBossClassLoadingUseCases

 

Preloading classes at startup

 

Debugging class loading issues

https://developer.jboss.org/wiki/ClassLoadingConfiguration

JBoss ClassLoader Introduction

 

This article is about the new classloader implementation and additional abstractions that use it from JBoss5.JBoss ClassLoader History are not covered by this document.

 

The JBoss ClassLoader framework is made up of a number of abstractions at different levels.The purpose of this introduction is give a high level overview of what each part of the framework does. The different abstractions exist to accomplish one of the goals of the JBoss ClassLoader project which is to allow different users to consume only the parts they want.

 

JBoss ClassLoader Implementation 

 

The JBoss ClassLoader project is the runtime implementation of the classloader framework. If you just want the basic functionality of the classloader then you can use this level directly. Here you can create ClassLoaderPolicys that define each classloader‘s rules and link them together to create a peer delegate classloading system. Since this is the runtime model, it is this level that the optional JMX management exists.

 

JBoss ClassLoading

 

The JBoss ClassLoading project is the deployment time framework that allows classloaders to be constructed from ClassLoadingMetaData. Rather than dealing with constructing policies and manually linking them together, you specify requirements and capabilities for each ClassLoading Module. The system then links these requirements to capabilities as they are satisifed and checks their consistency. You can think of this level as a kind of dependency injection framework for classloaders. As this is the deployment time model, it this level that can expose the "managed object" view to the JBoss profile service and management console.

 

JBoss ClassLoading - VFS

 

The VFSClassLoader provides an implementation of the ClassLoaderPolicy using the JBoss Virtual File System project.This can be used directly or in the JBoss ClassLoadingframework.

 

There is a seperate option that allows you to construct your modules insideJBossMicrocontainer configuration. This can be seen in use in the bootstrap configuration files of JBoss5.

Others

Built on top of these layers are the ClassLoading Deployers which allow for easy construction of classloaders from JavaEE deployments (or any other type of deployment). This includes mapping of legacy configuration to the ClassLoadingMetaData.

Additionally there is a MockClassLoaderPolicy which some may find useful to test or implement classloading scenarios in unit tests.

https://developer.jboss.org/wiki/JBossClassLoaderIntroduction

 

http://blog.163.com/javaee_chen/blog/static/17919507720116149511489/将一个完整的.war包部署到Jboss容器中,启动后报如下错误:

15:04:48,632 ERROR [ContextLoader] Context initialization failed
org.springframework.beans.factory.BeanCreationException: Error creating bean with name ‘org.apache.activemq.xbean.XBeanBrokerService#0‘ defined in ServletContext resource [/WEB-INF/applicationContext.xml]: Invocation of init method failed; nested exception is java.lang.NoSuchMethodError: org.slf4j.MDC.getCopyOfContextMap()Ljava/util/Map;
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1338)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:473)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory$1.run(AbstractAutowireCapableBeanFactory.java:409)
at java.security.AccessController.doPrivileged(Native Method)
分析情况:
在jboss根目录下执行如下命令
$find . -name slf4j*.jar
./bin/configuration/org.eclipse.osgi/bundles/24/1/.cp/slf4j-log4j12-1.4.3.jar
./bin/configuration/org.eclipse.osgi/bundles/24/1/.cp/slf4j-api-1.4.3.jar
./server/default/deploy/configuration/org.eclipse.osgi/bundles/14/1/.cp/slf4j-log4j12-1.4.3.jar
./server/default/deploy/configuration/org.eclipse.osgi/bundles/14/1/.cp/slf4j-api-1.4.3.jar
./server/default/deploy/etl_sngps.war/WEB-INF/lib/slf4j-api-1.6.1.jar
./server/default/deploy/etl_sngps.war/WEB-INF/lib/slf4j-log4j12-1.6.1.jar
./server/default/deploy/jboss-web.deployer/configuration/org.eclipse.osgi/bundles/14/1/.cp/slf4j-log4j12-1.4.3.jar
./server/default/deploy/jboss-web.deployer/configuration/org.eclipse.osgi/bundles/14/1/.cp/slf4j-api-1.4.3.jar
明明项目中lib地下的是1.6版本的,为什么还提示java.lang.NoSuchMethodError: org.slf4j.MDC.getCopyOfContextMap()Ljava/util/Map;(注:1.4一下版本会报这个错误,因为其不存在这里面的某个方法)
 
查看Jboss jar加载文档:
1) org.jboss.Main.main(String[]) 为入口.
2) main 函数创建一个名叫”jboss”的线程组, 然后创建一个属于该组的线程, 在线程中执行boot方法.
3) boot 方法首先处理main函数中的参数(及一些其它的系统环境设置), 接着就用系统的属性创建了org.jboss.system.server.ServerLoader实例[new ServerLoader(props)].
4) ServerLoader 注册Jboss相关的类路径, 包括XML解析器, jboss-jmx.jar, concurrent.jar及其它的一些额外的类路径.
这里一般都是在JBOSS_HOME\lib下面的jar.
5) ServerLoader 通过load(ClassLoader)方法创建Jboss Server实例. 参数ClassLoader是ClassLoader parentCL = Thread.currentThread(). getContextClassLoader( )得到的当前线程的类加载器. 创建的Server实例是org.jboss.system.server.Server接口的实现. load(ClassLoader)方法的细节:
? 用jar包及在ServerLoader中注册的类路径创建一个URLClassLoader的实例, 把传入的ClassLoader作为该URLClassLoader的parent.
? Server 接口的实现类由系统属性 jboss.server.type决定, 默认是 org.jboss.system.server.ServerImpl.
? URLClassLoader 通过无参构造函数加载Server接口实现的实例. 在加载前把当前线程的类加载器置为该URLClassLoader, 在加载完成后再置回之前传入的ClassLoader.
 
6) Server 实例用系统属性进行初始化[server.init(props)].
7) 服务起动[server.start()]. 起动过程的默认实现如下:
? 把当前线程类型加载器置为加载该Server接口实现实例的ClassLoader.
? 在jboss域内, 通过MBeanServerFactory的createMBeanServer(String)方法创建MbeanServer实例.
? 在MBean Server上注册ServerImpl和ServerConfigImpl两个MBean.
? 初始化统一的类加载仓库(unified class loader repository), 用来装载服务器配置目录及其它可选目录下的jar文件. 对于每一个jar文件和类目录都会创建一个相应的org.jboss.jmx.loading.UnifiedClassLoader实例, 并且注册到统一的仓库中. 其中一个UnifiedClassLoader实例会被设置为当前线程上下文的ClassLoader. [?: This effectively makes allUnifiedClassLoaders available through the thread context class loader.]
? 接下来创建org.jboss.system.ServiceController的MBean实例. ServiceController管理JBoss MBean服务的生命周期.
 
需要注意的是:JBOSS在加载自带的核心JAR之后,将会优先加载下面的两个目录
1、D:\jboss\server\default\lib
2、D:\jboss\server\default\tmp\deploy
 
但是上面三组均不在以上1 2 所指的2个目录中。接着看......
找到如下文件,注意这个文件里面蕴藏着jar加载的有一个规则.
\jboss-4.2.3.GA\server\default\conf\xmdesc org.jboss.deployment.MainDeployer-xmbean.xml
最先加载的是后缀名为deployer目录下应用或者服务;
250:.rar,300:-ds.xml,400:.jar,500:.war,550:.jse,650:.ear,800:.bsh
<descriptors>
<value value="250:.rar,300:-ds.xml,400:.jar,500:.war,550:.jse,650:.ear,800:.bsh"/>
</descriptors>
可以通过调整这个value来改变加载规则。
 
这里已经很清楚了,上面所引爆的问题,正是由于/jboss-web.deployer下面所用的1,4版本导致的。删除后,一切正常。
这里面还有一个问题,有些时候我们在使用jboss容器前,应该认真的看下jboss目录的机构及大致各个目录的作用,然后做一些精简删除无用的或者无关精要的目录,不仅可以让jboss瘦身还能减少问题引发的根源。
http://www.cnblogs.com/svennee/p/4075511.html

 

http://liufei-fir.iteye.com/blog/759772初次部署jboss的web应用,把tomcat/weblogic下的工程移植到jboss上发布

一、修改JBOSS应用服务器连接的数据库和端口:

1、端口修改:

4.*版: JBOSS H OME/server>default>deploy>jbossweb.sar>server.xml5.: JBOSSHOME/server−−>default−−>deploy−−>jbossweb.sar−−>server.xml5.∗版: {JBOSS_HOME}/server-->default-->deployers-->jbossweb.deployer-->server.xml

一般oracle的端口是8080,把8080改成其他端口即可:

<Connector port="8888" address="jboss.bind.address"maxThreads="250"maxHttpHeaderSize="8192"emptySessionPath="true"protocol="HTTP/1.1"enableLookups="false"redirectPort="8443"acceptCount="100"connectionTimeout="20000"disableUploadTimeout="true"/>2: jboss.bind.address"maxThreads="250"maxHttpHeaderSize="8192"emptySessionPath="true"protocol="HTTP/1.1"enableLookups="false"redirectPort="8443"acceptCount="100"connectionTimeout="20000"disableUploadTimeout="true"/>2、连接的数据库各种数据库的连接模板格式见: {JBOSS_HOME}/doc/examples/jca

将配置文件拷贝到JBOSS H OME/server/default<datasources><localtxdatasource><jndiname>trafficMips</jndiname><connectionurl>jdbc:oracle:thin:@192.168.10.235:1521:ora10</connectionurl><driverclass>oracle.jdbc.driver.OracleDriver</driverclass><username>goods</username><password>goods</password>.............JDBCJBoss H OME\server\default\libJBOSSHOME/server/default目录下如:<datasources><local−tx−datasource><jndi−name>trafficMips</jndi−name><connection−url>jdbc:oracle:thin:@192.168.10.235:1521:ora10</connection−url><driver−class>oracle.jdbc.driver.OracleDriver</driver−class><user−name>goods</user−name><password>goods</password>.............注意:连接数据库所用到的JDBC驱动程序要拷贝到JBossHOME\server\default\lib目录下二、工程配置的修改在 {war_file}/web-inf/下增加文件 jboss-web.xml:

内容如下:

<?xml version="1.0" encoding="ISO-8859-1"?>

<!DOCTYPE jboss-web PUBLIC
"-//JBoss//DTD Web Application 2.3V2//EN"
"http://www.jboss.org/j2ee/dtd/jboss-web_4_0.dtd">

<jboss-web>
<resource-ref>
<res-ref-name>jdbc/goodsDB</res-ref-name>
<jndi-name>java:/trafficMips</jndi-name>
</resource-ref>
</jboss-web>

注意:jndi-name跟你的数据库连接源相对应....

web.xml文件加入如下:

<resource-ref>
<res-ref-name>jdbc/goodsDB</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
<res-auth>Container</res-auth>
</resource-ref>

三、注意的问题

1、ibatis不需要专门的配置文件,Hibernate好像需要另外的配置.....待查找学习

2、jboss下和工程的ClassLoader的思考,两边包含的类库版本必须一致,不然会冲突,jboss起来的时候是先加载 JBOSS H OME/server\default\lib,springdwr,spring.jarJBOSSHOME/server\default\lib下的,如spring和dwr的关系,起服务的发现必须把spring.jar包先放在 {JBOSS_HOME}/server\default\lib预先加载,才能读到 dwr,不然放在工程lib下会先加载dwr而找不到spring.jar,跟tomcat不同...不知道为什么?

3、注意jboss的版本问题,一般4.*都比较稳定,我用了一个5.*的,结果老是提示找不到struts和servle类,无论放哪里都是一样,很奇怪.....,换了4.*就没问题,5.*集成的是6.*的tomcat,我单独用6.*的tomcat起服务也没什么问题的

四、 其他jboss注意的和思考的

1、jboss下ClassLoader的思考: http://www.iteye.com/topic/173561

2、JBOSS维护经验 : http://dapeng.iteye.com/blog/152373

3、hibernate部署: http://jackytang520.iteye.com/blog/297644

http://www.cnblogs.com/svennee/p/4075516.html

 

classloader

标签:

原文地址:http://www.cnblogs.com/softidea/p/5608913.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!