簡體   English   中英

Ecplise Java JNI,java.lang.UnsatisfiedLinkError加載dll

[英]Ecplise Java JNI, java.lang.UnsatisfiedLinkError loading dll

我在加載打印機dll時遇到問題。 我有一個打印機制造商的dll文件(JniPrinterStatusLib.dll)。 我寫了像打印機制造商建議的代碼。 代碼是:

package com.printer.test

public class JniPrinterStatus {
    static{
        System.loadLibrary("JniPrinterStatusLib");
    }

    public native int GetStatus(String printer);
}
package com.printer.test

public class TestSample {
    public static void main(String[] args) {
        int status;
        String printer = "MY PRINTER";
        JniPrinterStatus jps = new JniPrinterStatus();

        System.out.println("PRINTER NAME = " + printer);

        status = jps.GetStatus(printer);
        if (status == -1) {
            System.out.println("status = -1");
        }
        else if (status == 0) {
            System.out.println("status = NORMAL");
        }
        else if ((status & 0x00000080) != 0) {
            System.out.println("status = PRINTER_STATUS_OFFLINE");
        }
        else if ((status & 0x00400000) != 0) {
            System.out.println("status = PRINTER_STATUS_DOOR_OPEN");
        }
        else if ((status & 0x00000010) != 0) {
            System.out.println("status = PRINTER_STATUS_PAPER_OUT");
        }
        else if ((status & 0x00000800) != 0) {
            System.out.println("status = PRINTER_STATUS_OUTPUT_BIN_FULL");
        }
        else if ((status & 0x00000040) != 0) {
            System.out.println("status = PRINTER_STATUS_PAPER_PROBLEM");
        }
   }
}

我用Eclipse運行代碼,我把dll庫放在文件夾項目中,錯誤是

PRINTER NAME = MY PRINTER
Exception in thread "main" java.lang.UnsatisfiedLinkError: com.printer.test.JniPrinterStatus.GetStatus(Ljava/lang/String;)I
    at com.printer.test.JniPrinterStatus.GetStatus(Native Method)
    at com.printer.test.TestSample.main(TestSample.java:10)

如果我將源代碼“com.printer.test”移動到默認包,代碼將工作並顯示:

PRINTER NAME = MY PRINTER
status = -1

我不知道怎么可能。 如果我從命令提示符編譯並運行代碼而沒有包它可以工作。

問題出在哪兒?

謝謝

對不起,實際上我想寫評論,但由於我的聲譽仍然很低,我不得不嘗試猜測答案。

  • 應該沒有必要重新編譯DLL - 它只是一些要調用的本機代碼。
  • 加載dll的類的java包也不應該有所作為。

您必須注意您的系統架構:64位DLL文件將在32位JRE中失敗,反之亦然。 確保您的JRE架構與dll架構相匹配。

另一件需要考慮的事情是你的工作目錄。 Eclipse可能使用的工作目錄與從控制台運行程序時使用的工作目錄不同。

最后但並非最不重要的,請查看您的java.library.path變量。

此頁面也可能有所幫助: https//www.chilkatsoft.com/java-loadLibrary-Windows.asp我將介紹所有細節。

來自類UnsatisfiedLinkErrorjavadoc ...

如果Java虛擬機無法找到聲明為native的方法的適當本機語言定義,則拋出該異常。

這意味着找不到函數Java_com_printer_test_JniPrinterStatus_GetStatus

java.lang.System方法loadLibrary通常搜索[System]屬性“java.library.path”中列出的目錄。 對於Windows機器,此屬性的值通常是PATH環境變量的值。

因此,我建議在代碼中打印出該屬性的值,以查看它是否包含包含DLL的目錄。 如果沒有,則需要通過重新定位DLL或更改PATH環境變量或使用-Djava.library.path=...選項啟動java程序來解決此問題。 之后,您需要檢查本機方法的簽名。 Dependency Walker是我在工作中用來完成此任務的工具。

編輯重新閱讀您的問題,我覺得我沒有准確地解決您的問題,所以讓我補充一下......

Eclipse的默認行為是將資源文件(如DLL)復制到輸出文件夾。 因此,如果您將DLL放在文件夾src\\com\\printer\\test ,它將獲得復制到bin\\com\\printer\\test文件夾。 我的猜測是當前的工作目錄,即. 在你的“java.library.path”中,這就是當你的java代碼在默認包中時它可以工作的原因。

預期的Java類包在JNI庫中進行了硬編碼。 在您的情況下,它是默認包。

讓我擴展一下。 當在JNI庫中實現本機方法時,必須使用以下格式的名稱創建公共C函數:

Java_com_mypackage_MyClass_MyMethod

換句話說,JNI庫無法為任意包中的類提供方法 - 僅適用於JNI庫作者所考慮的包中的類。

在你的情況下,它是默認的。 C函數轉到Java_JniPrinterStatus_GetStatus 如果調用類MyPrinterStatus ,或將其放入com.foobar包中,則JNI運行時將無法將C函數與聲明的Java本機方法相關聯。 這就是JNI的設計方式。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM