JBoss jar包沖突及jar加載順序


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瘦身還能減少問題引發的根源。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM