Jboss classloader 机制

1 类装载器
Java中的Class实例,不仅是全限定名(包名+类名)的函数,也是类装载器的函数,即:Class = f(name,Li,Ld)其中name表示为全限定名,Li为初始类装载器,Ld为定义类装载器初始装载器;初始类装载器为在其上发生loadClass调用返回Class实例的那个装载器;定义装载器则是实际为Class实例执行defineClass,从bytecode中读入类定义的那个装载器。因为loadClass方法可以被子类重载,其中对defineClass的调用有可能被委派给其它装载器做,(具体含义,参见java classloader 的双亲委派机制—《深入JAVA虚拟机》一书有比较深入的讲解)所以Li和Ld不一定相同。
于是, 两个不同类装载器装载的类,即使类全限定名相同,都不能相互cast,否则抛出ClassCastException。
如果装载器L1装载的类p.A有包可见的方法f,则装载器L2装载的类p.B不能访问f,否则抛出IllegalAccessException。
如果有Class1和Class2的name,Li相同,而Ld不同,它们实例之间的引用赋值时会触发装载限制检查,抛出LinkageError。

2 JBoss的Classloader机制
概念介绍
UCL:org.jboss.mx.loading.UnifiedClassLoader3,他继承了标准的java.net.URLClassLoader,覆盖了标准的parent delegation模型以使用共享class和资源仓库(respository)org.jboss.mx.loading.UnifiedLoaderRepository3
Jboss Classloader 实现机制
平面模型:
JBoss实现了自己的类装载器UnifiedClassLoader3,一般来说,一个顶层的deployment就有一个UnifiedClassLoader3实例为之工作。一个deployment所装载的类,其他deployment是可见的,全局唯一的UnifiedLoaderRepository3实例用于管理这些类,以及转载他们的UnifieClassLoader3实例。UnifiedLoaderRepository3实例和UnifieClassLoader3实例是一对多的关系。
在%JBOSS_HOME%/server/<profile>/conf/jboss-service.xml中有如下配置:
<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是根据文件的后缀进行区分。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包,它首先会调用仓库去loadclass(即从UnifiedLoaderRepository3实例中查找看是否已经加载过),仓库在查找无果的情况下会回调各自的UCL去加载本地库。否则就是采用独立SERVLET规范定义的classloader(即WebAppClassLoader)加载。

隔离的(scope)JBOSS 应用ClassLoader机制:
每一个隔离的JBOSS应用都有一个自己的私有仓库,org.jboss.mx.loading.HeirarchicalLoaderRepository3,此类继承自公用仓库类,org.jboss.mx.loading.UnifiedLoaderRepository3。scope配置只能是顶级下的配置,比如一个.sar中包括.war都配置了scope只有.sar下的META-INF/jboss-service.xml才有效,这与前面的Top Level Deployer + Top Level Ucl对应,
针对.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>
<loader-repository> com.example:loader=unique-archive-name </loader-repository>
</jboss-web>
针对典型的ear+war应用,*.ear/META-INF/jboss-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>
配置UseJBossWebLoader为true时,webapp将使用jboss隔离的UCL作为classloader,并且是否parent load模型是由其中的java2ParentDelegation参数决定,java2ClassLoadingCompliance属性会被忽略;
配置UseJBossWebLoader为false,则webapp的加载时通过独立于jboss的classloader即WebAppClassLoader来加载,配置java2ClassLoadingCompliance为true,则表明是选择parent first,典型的classloader双亲委派模型,否则采用child first,先从自身加载,找不到再请父亲加载。
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值