天天看點

虛拟主機同時運作多個使用 ImageMagick +Jmagick的網站

       Tomcat虛拟主機同時運作多個使用 ImageMagick +Jmagick的網站,遇到了這個錯誤:Native Library C:\WINDOWS\system32\jmagick.dll already loaded in another classloader

-----------------------------------------------------

環境說明:

中間件:tomcat6.0.18

開發環境:winXP

伺服器:CentOS5.3

         在一個tomcat下,有多個虛拟主機, 運作了多個網站,每個網站都使用 ImageMagick +Jmagick 來處理圖檔, 須要使用JNI調用本地*.dll檔案來處理圖檔,  每個網站(web應用程式)都有自己的lib,在WebContent\WEB-INF\lib下面.  這樣就有重複的jar包, 如jmagick.jar,servlet-api.jar, ***等好多jar包, 在每個網站(web應用程式)都有一份.

-----------------------------------------------------

結果在啟動tomcat時會報:

1 忽略了servlet-api.jar .  (具體日志資訊沒有複制)

2 一個web應用程式處理完圖檔後,第二個web應用程式再處理圖檔時會出錯:Native Library C:\WINDOWS\system32\jmagick.dll already loaded in another classloader

3 A C3P0Registry mbean is already registered

-----------------------------------------------------

我搜尋到了  http://jbossweek.iteye.com/blog/138903的一篇文章:

1、症狀 

如果JBoss上的兩個web應用需要使用相同的JNI本地庫,當第二個web應用加載JNI本地庫時,就會出現Native Library xxx.so already loaded in another classloader錯誤

2、原因 

 Java虛拟機為了在JNI本地庫中確定基于classloader的命名空間隔離,因而不允許一個JNI本地庫被兩個不同的classloader加載。而JBoss中web應用的classloader是獨立的,也就是說每個web應用都有一個專屬的classloader,這樣就出現兩個classloader加載同一JNI本地庫的情況

3、解決方法 

在JBoss AS中,雖然不同的web應用使用不同的classloader,但是web應用classloader的父classloader是相同的,這樣根據雙親委托模型隻要讓父classloader加載JNI本地庫就可以避免被多個classloader加載。父classloader的classpath為JBoss AS配置(default、all或minimal)的lib目錄,因而隻要将JNI class單獨釋出成jar包,并放在配置(default、all或minimal)的lib目錄中,問題就可以解決
           

 以上說明了問題的原因, 上面說 "因而隻要将JNI class單獨釋出成jar包"  , 我使用了 jmagick.jar是在這裡調用了JNI ,  是以把jmagick.jar 從WebContent\WEB-INF\lib下 移動到了E:\tomcat-6.0.18\lib下, 就不會被重複加載了.

----------------------------------------------------

Tomcat6的類加載順序:

1、最先是$JAVA_HOME/jre/lib/ext/下的jar檔案。

2、環境變量CLASSPATH中的jar和class檔案。

3、$CATALINA_HOME/lib 下的jar檔案。

4、各自具體的webapp /WEB-INF/classes下的class檔案。

5、各自具體的webapp /WEB-INF/lib下的jar檔案。