java.lang.UnsatisfiedLinkError解決方法彙集(轉載)

J2EE引擎出現java.lang.UnsatisfiedLinkError: CC錯誤的原因(2008-03-04 11:03:29)
 

運行JSP報表程序頁面出現java.lang.UnsatisfiedLinkError: CC錯誤有以下幾種原因和處理方法:

1、請查看控制檯的錯誤信息
a:如果控制檯的消息是類似

java.lang.UnsatisfiedLinkError: no MRChkLib in java.library.path,Error loading library MRChkLib

這樣的錯誤信息,那麼是因爲MRChkLib.dll沒有拷貝到windows的System32目錄下.(MRChkLib.dll是加密鎖的JAVA接口文件,文件在報表安裝目錄DogDriver/JavaAPI下可以找到)並且要注意PATH環境變量中要包含System32目錄。(如果服務器操作系統是Linux,那麼使用報表安裝目錄DogDriver/JavaAPI下的libMRChkLib.so文件,將libMRChkLib.so複製到WebServer的啓動bin目錄。如果在這個目錄下仍然出現cannot load library錯誤,請設置系統環境變量LD_LIBRARY_PATH的值爲libMRChkLib.so所在的目錄。
例如:如果libMRChkLib.so在/somedir目錄下,則 export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/somedir)

b:如果控制檯的消息是類似

java.lang.unsatisfiedLinkError:native libery c:/winnt/system32/mrchklib.dll already loaded in anotherclassLoader error loading mrchklib.dll

這樣的錯誤信息,那麼是因爲WebAPP在重新被啓動之後,無法再次加載動態庫造成的,這是java的約束,Java不允許一個實例加載多次動態庫.可以這樣解決,將mr.jar拷貝到WebServer的lib目錄,刪除/WEB-INF/lib目錄下的mr.jar,然後重新啓動webserver。


2、如果一個webserver上有多個報表應用,請將/WEB-INF/lib/mr.jar移動到WebServer的lib目錄下,確保每一個Web應用程序目錄下都沒有mr.jar,而只有WebServer的lib目錄下有該文件,重啓webserver.


3、一個Webserver上只能有一個mr.jar文件,刪掉多餘的mr*.jar文件,然後清除webserver臨時文件,重新啓動webserver。
===================================================================================
最近項目中用到了jni,於是安裝了eclipse的cdt和MinGW來用,以前沒怎麼動過C語言,網上找了下教程,倒是挺容易的,一路弄下來也沒提示什麼錯誤,但是在最後調用本地方法時卻遇到了大麻煩,總是提示找不到方法。即使一個簡單的HelloWorld,也是一樣
Exception in thread "main" java.lang.UnsatisfiedLinkError: HelloWorld.print()V
奇怪了,loadLibrary()沒有問題,怎麼會找不到方法呢?用dll export viewer察看,導出的方法爲
函數名 地址 偏移量
Java_HelloWorld_print@8 0x67741250 0x00001250

實在沒辦法了,只好安裝龐大的visual studio重新來編譯,調用成功了!
再次用dll export viewer查看,發現函數名的前面多了一條下劃線
函數名 地址 偏移量
_Java_HelloWorld_print@8 0x67741250 0x00001250
看來是給MinGW少傳了某個參數,經過網上查閱資料,終於找到一個解決方案:給MinGW的ld命令指定一個參數--kill-at即可
gcc -Wl, --kill-at -shared -o jnihello.dll HelloWorld.c
再次用dll export viewer查看,發現導出的函數名稱變爲
函數名 地址 偏移量
Java_HelloWorld_print 0x67741250 0x00001250

--kill-at指令去掉了函數名稱後綴的@,並沒有像msvc那樣添加前綴的下劃線
========================================================================
現象: java.lang.UnsatisfiedLinkError: Native Library xxx.dll alreadyloaded in another classloader atjava.lang.ClassLoader.loadLibrary0(ClassLoader.java:1551) atjava.lang.ClassLoader.loadLibrary(ClassLoader.java:1511) atjava.lang.Runtime.loadLibrary0(Runtime.java:788) atjava.lang.System.loadLibrary(System.java:834) 分析:這種錯誤在我們使用熱啓動方式發佈某個使用了JNI技術的Web應用時,並將調用年native方法的jar包獨立部署在該應用下面,當我們的Web應用有了更新以後,在調用到該jar包封裝的native方法時,會拋出該錯誤。(以上OS爲Windows,若是Linux或Unix,應該是xxx.so報錯) 這是因爲Web服務器已經在第一次加載該應用時,已經load了該dll,當該應用被再次熱啓動時,該dll將重新被加載,於是報錯。解決方案: 一、將含有JNI調用的jar包部署在Web服務器的公用lib庫中。Web應用再發布時可以不用加載;二、jar包部署不變,在該Web中實現一個listener,監聽是否第一次啓動,若不是第一次啓動,屏蔽掉該jar包所含dll的加載。
========================================================================
類裝入問題:UnsatisfiedLinkError
作者:Simon Burns 來源:IBM 整理日期:2007-6-3

UnsatisfiedLinkError

在把本機調用鏈接到對應的本機定義時,類裝入器扮演着重要角色。如果程序試圖裝入一個不存在或者放錯的本機庫時,在鏈接階段的解析過程會發生 UnsatisfiedLinkError。JVM 規範指定 UnsatisfiedLinkError 是:

對於聲明爲 native 的方法,如果 Java 虛擬機找不到和它對應的本機語言定義,就會拋出該異常。

當調用本機方法時,類裝入器會嘗試裝入定義了該方法的本機庫。如果找不到這個庫,就會拋出這個錯誤。

清單 6 演示了拋出 UnsatisfiedLinkError 的測試用例 :



清單 6. UnsatisfiedLinkError.java
                        public class UnsatisfiedLinkErrorTest {
                        public native void call_A_Native_Method();
                        static {
                        System.loadLibrary("myNativeLibrary");
                        }
                        public static void main(String[] args) {
                        new UnsatisfiedLinkErrorTest().call_A_Native_Method();
                        }
                        }

這段代碼調用本機方法 call_A_Native_Method(),該方法是在本機庫 myNativeLibrary 中定義的。因爲這個庫不存在,所以在程序運行時會發生以下錯誤:

The <a target=_blank class="homepage" href="http://www.gold98.net/artics/java/">java</a> class could not be loaded. <a target=_blank class="homepage" href="http://www.gold98.net/artics/java/">java</a>.lang.UnsatisfiedLinkError:
                        Cant find library myNativeLibrary  (myNativeLibrary.dll)
                        in sun.boot.library.path or <a target=_blank class="homepage" href="http://www.gold98.net/artics/java/">java</a>.library.path
                        sun.boot.library.path=D:/sdk/jre/bin
                        <a target=_blank class="homepage" href="http://www.gold98.net/artics/java/">java</a>.library.path= D:/sdk/jre/bin
                        at <a target=_blank class="homepage" href="http://www.gold98.net/artics/java/">java</a>.lang.ClassLoader$NativeLibrary.load(Native Method)
                        at <a target=_blank class="homepage" href="http://www.gold98.net/artics/java/">java</a>.lang.ClassLoader.loadLibrary0(ClassLoader.<a target=_blank class="homepage" href="http://www.gold98.net/artics/java/">java</a>:2147)
                        at <a target=_blank class="homepage" href="http://www.gold98.net/artics/java/">java</a>.lang.ClassLoader.loadLibrary(ClassLoader.<a target=_blank class="homepage" href="http://www.gold98.net/artics/java/">java</a>:2006)
                        at <a target=_blank class="homepage" href="http://www.gold98.net/artics/java/">java</a>.lang.Runtime.loadLibrary0(Runtime.<a target=_blank class="homepage" href="http://www.gold98.net/artics/java/">java</a>:824)
                        at <a target=_blank class="homepage" href="http://www.gold98.net/artics/java/">java</a>.lang.System.loadLibrary(System.<a target=_blank class="homepage" href="http://www.gold98.net/artics/java/">java</a>:908)
                        at UnsatisfiedLinkErrorTest.<clinit>(UnsatisfiedLinkErrorTest.<a target=_blank class="homepage" href="http://www.gold98.net/artics/java/">java</a>:6)
                        

本機庫的裝入由調用 System.loadLibrary() 方法的類的類裝入器啓動 —— 在清單 6 中,就是 UnsatisfiedLinkErrorTest 的類裝入器。根據使用的類裝入器,會搜索不同的位置:

  • 對於由 bootstrap 類裝入器裝入的類,搜索 sun.boot.library.path
  • 對於由擴展類裝入器裝入的類,先搜索 java.ext.dirs,然後是 sun.boot.library.path,然後是 java.library.path
  • 對於由系統類裝入器裝入的類,搜索 sun.boot.library.path,然後是 java.library.path

在清單 6 中,UnsatisfiedLinkErrorTest 類是由系統類裝入器裝入的。要裝入所引用的本機庫,這個類裝入器先查找 sun.boot.library.path,然後查找 java.library.path。因爲在兩個位置中都沒有需要的庫,所以類裝入器拋出 UnsatisfiedLinkageError

==========================================================================

java.lang.UnsatisfiedLinkError出現這種錯誤的原因是一般是java虛擬機找不到聲明爲native方法的本地語言定義時,出現的錯誤。在我的理解過程中我一般都認爲是由於導入dll或者導入lib文件不正確導致的。有些需要靜態導入就沒有問題(即在前面加static來導入lib文件),如果是不加static導入也就是動態導入的時候,那麼需要添加catch的拋出異常來解決,如

try{
    System.loadLibrary("vtkCommonJava");
    System.loadLibrary("vtkFilteringJava");
    System.loadLibrary("vtkIOJava");
    System.loadLibrary("vtkImagingJava");
    System.loadLibrary("vtkGraphicsJava");
    System.loadLibrary("vtkRenderingJava");
   }catch(Throwable e)
   {
    System.out.println("The load problem");
   }

這種方式來判斷,或者直接在類前面添加

static{

   System.loadLibrary("vtkCommonJava");
    System.loadLibrary("vtkFilteringJava");
    System.loadLibrary("vtkIOJava");
    System.loadLibrary("vtkImagingJava");
    System.loadLibrary("vtkGraphicsJava");
    System.loadLibrary("vtkRenderingJava");

}
================================================================================
關於java.lang.UnsatisfiedLinkError(JNI)
 
 
    目標:把pbp1.0的java包和native移到GEM中,並使GEM在新的虛擬機上正常運行
    背景:GEM(1)有一堆java包和native函數,pbp1.0是虛擬機和JAVA基本包,要將pbp1.0的虛擬機移走只用它的JAVA基本包和native函數。
    問題:在將GEM和pbp1.0的native函數生成一個動態庫後在程序裏System.loadLibrary()無法加載,報java.lang.UnsatisfiedLinkError
    解決過程:
    1,理論
   我們知道,JAVA調用native函數時,必須通過System.loadLibrary()或System.load將其native函數所在動態庫加載到虛擬機。並在運行時指明-Djava.library.path或-Dsun.boot.library.path,將其指向包含有native函數的動態庫所在位置。
    2,實施
   我按這個步驟操作完成後就是無法加載我生成的動態庫libgem.so,這個庫用到的其他動態庫包括:rt,pthread,freetype,dl,directfb,而directfb用到的動態庫有rt,dl,pthread,freetype,jpeg,png,這些庫除了directfb要生成外其餘都在/lib目錄下存在。
    3,思路
    先寫了一個Hello的測試用例。發現在native裏所使用到其他動態庫時,無論是否存在於相關目錄,仍然無法加載。然後經過修改編譯選項,把所使用到的動態庫連動態連接進目標庫,如下:
    $(GCC) -fPIC -shared -o libdirectfb.so ... -lpng -ljpeg -lpthread -lrt -ldl, -lfreetype
    經過這麼一個修改後,directfb可以加載。
   這也說明System.loadLibrary()所加載的動態庫所引用的所有符號都要能找到。如果有一個無法找到將無法加載。可以寫一個空的main()函數,對你的動態庫進行連接,如果動態庫裏所引用的符號在指定的動態庫和本身找到不到則無法編譯通過,那麼這個動態庫也肯定加載不了。
    4,問題解決
    按照這個思路,對libgem.so的編譯Makefile做相應修改後,問題解決!並在LD_LIBRARY_PATH加入動態庫所在目錄。

(1)MHP (Multimedia Home Platform) was developed by the DVB Project as theworld's first open standard for interactive television. It is aJava-based environment which defines a generic interface betweeninteractive digital applications and the terminals on which thoseapplications execute. MHP was designed to run on DVB platforms butthere was a demand to extend the interoperability it offers to otherdigital television platforms. This demand gave rise to GEM, or Globally Executable MHP, a framework which allows other organisations to define specifications based on MHP.

====================================================================================

另外,還可能是dll本身的問題,使用release版的,而不要用debug版的

=============================================================================

關於編寫JNI時的發生的unsatisfiedlinkError錯誤- -

 

 

這個錯誤也讓我鬱悶了半天,現在我把它寫出來,可以讓大家少走點彎路。一般這個錯誤有兩種:

1。unsatisfiedlinkError:dll,那說明你沒有把dll放到合適的位置,一般就和要調用原生函數的類放在一起,當然前提是你成功的生成dll了

2。unsatisfiedlinkError:方法名,這個時候你其實dll已經成功生成了,而且位置也正確,它的意思就是你沒有定義那個函數,你可能會說,我明明定義了,其實當你發現問題所在,你只能自虐了,肯定是你在C文件中定義函數時有些字母大小寫錯了,因爲其他地方是自動生成的,不會出錯。尤其是直接從網上拷貝源程序時經常發生這種問題,有些作者不負責任,把有錯誤的程序也貼上去。

 

轉自:http://www.360doc.com/content/090402/09/107226_2994393.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章