2012-07-10 34 views
3

我想爲第三方DLL製作Java包裝。我創建了自己的DLL,充當JNI和第三方DLL之間的中間人。在Java中我加載這個DLL很好,但返回錯誤java.lang.UnsatisfiedLinkError: sixense.Sixense.init()Z。什麼可能導致這個錯誤,我該如何正確調試它?當調用本地方法時返回java.lang.UnsatisfiedLinkError

Main.java:

package sixense_test; 

import sixense.ControllerData; 
import sixense.Sixense; 

public class Main { 

    public static ControllerData[] controllers = new ControllerData[4]; 
    public static boolean quit; 

    public static void main(String[] args) { 
     if(Sixense.init()) { 
      Sixense.setActiveBase(0); 
      Sixense.getAllNewestData(controllers); 
      System.out.println("X: " + controllers[0].pos[0] + "Y: " + controllers[0].pos[1] + "Z: " + controllers[0].pos[2]); 
     } 
    } 
} 

Sixense.java:

package sixense; 

public class Sixense { 
    public static native boolean init(); 
    public static native boolean exit(); 
    public static native int getMaxBases(); 
    public static native boolean setActiveBase(int base_num); 
    public static native boolean isBaseConnected(int base_num); 
    public static native int getMaxControllers(); 
    public static native int getNumActiveControllers(); 
    public static native boolean isControllerEnabled(int controller_id); 
    public static native boolean getAllNewestData(ControllerData[] all_data); 
    public static native boolean getAllData(int index_back, ControllerData[] all_data); 
    public static native boolean getNewestData(int controller_id, ControllerData data); 
    public static native boolean getData(int controller_id, int index_back, ControllerData all_data); 
    public static native int getHistorySize(); 
    public static native boolean setFilterEnabled(boolean on_or_off); 
    public static native boolean getFilterEnabled(); 
    public static native boolean setFilterParams(float near_range, float near_val, float far_range, float far_val); 
    public static native boolean getFilterParams(float[] params); 
    public static native boolean triggerVibration(int controller_id, int duration, int pattern_id); 
    public static native boolean autoEnableHemisphereTracking(int controller_id); 
    public static native boolean setHighPriorityBinding(boolean on_or_off); 
    public static native boolean getHighPriorityBinding(); 
    public static native boolean setBaseColor(int red, int green, int blue); 
    public static native boolean getColorBase(int[] colors); 
    static { 
     System.loadLibrary("Sixense_Java"); 
    } 
} 

從sixense_Sixense.cpp的摘錄:

#include <jni.h> 
#include <sixense.h> 
#include "sixense_Sixense.h" 

JNIEXPORT jboolean JNICALL Java_sixense_Sixense_init(JNIEnv *env, jclass obj) { 
    int i; 
    i = sixenseInit(); 
    return (i == -1) ? JNI_FALSE : JNI_TRUE; 
} 

從sixense_Sixense.h的摘錄:

/* DO NOT EDIT THIS FILE - it is machine generated */ 
#include <jni.h> 
/* Header for class sixense_Sixense */ 

#ifndef _Included_sixense_Sixense 
#define _Included_sixense_Sixense 
#ifdef __cplusplus 
extern "C" { 
#endif 
/* 
* Class:  sixense_Sixense 
* Method: init 
* Signature:()Z 
*/ 
JNIEXPORT jboolean JNICALL Java_sixense_Sixense_init 
    (JNIEnv *, jclass); 
從DUMPBIN

輸出:

File Type: DLL 

    Section contains the following exports for Sixense_Java.dll 

    00000000 characteristics 
    4FFBC481 time date stamp Tue Jul 10 01:58:25 2012 
     0.00 version 
      1 ordinal base 
      23 number of functions 
      23 number of names 

    ordinal hint RVA  name 

      1 0 00001D10 [email protected] 
      2 1 000011A0 [email protected] 
      3 2 00001A40 [email protected] 
      4 3 000019A0 [email protected] 
      5 4 00001DC0 [email protected] 
      6 5 00001B30 [email protected] 
      7 6 00001BD0 [email protected] 
      8 7 00001C40 [email protected] 
      9 8 00001D60 [email protected] 
     10 9 00001B90 [email protected] 
     11 A 000011C0 [email protected] 
     12 B 00001210 [email protected] 
     13 C 00001AE0 [email protected] 
     14 D 00001220 [email protected] 
     15 E 00001180 [email protected] 
     16 F 000011F0 [email protected] 
     17 10 [email protected] 
     18 11 000011D0 [email protected] 
     19 12 00001D90 [email protected] 
     20 13 00001BA0 [email protected] 
     21 14 00001C00 [email protected] 
     22 15 00001D30 [email protected] 
     23 16 00001CE0 [email protected] 

    Summary 

     1000 .bss 
     1000 .data 
     1000 .edata 
     1000 .idata 
     1000 .rdata 
     1000 .reloc 
     2000 .text 
+1

你有-Djava.library.path虛擬機arg中的dll文件夾嗎? – 2012-07-10 19:07:02

+0

dumpbin /導出Sixense_Java.dll報告是什麼? – Petesh 2012-07-10 19:41:55

+0

這些DLL位於java.library.path的一個文件夾中,而@Petesh我剛剛添加了dumpbin的輸出。 – yodal 2012-07-10 21:14:44

回答

5

當調用Java中的原生功能,運行時嘗試使用:

  • 一個STDCALL風格的裝飾功能:[email protected],其中n是在參數列表中的字節數,
  • 和cdecl-style undecorated功能:functionName

當使用MinGW編譯,你會得到這兩種的混合:MinGW的將追加@n,但不會在前面加上下劃線:[email protected]

解決此問題的方法是告訴ld不要使用--kill-at開關(或如果通過GCC調用-Wl,--kill-at)添加後綴。

+0

這應該是公認的答案。 – Anton 2014-09-04 20:25:53

+0

你能否更深入地回答你的問題?我遇到與OP相同的問題,我使用makefile來調用javah來生成頭文件和g ++來生成.o和.dll。我正在使用MinGW,但@ n不會附加到任何函數名稱,也不會在前面加下劃線,儘管不像OP那樣簡單地修改文件(我知道,實際上不應該這樣做)實際上並沒有幫助。 – Troyseph 2014-10-01 10:53:41

1
java.lang.UnsatisfiedLinkError: no Sixense_Java in java.library.path 

看起來像Java不能找到庫,你把它放到正確的地方?

您可能需要更改java.library.path,看看this

如果你想打印它的內容使用:

System.out.println(System.getProperties().getProperty("java.library.path")); 

這可能會打印很多,你可能想split(";")和打印自己的每個條目。

+0

僅當我刪除庫以測試它是否發送了不同的錯誤消息時,才輸出該錯誤。 – yodal 2012-07-10 20:33:28

+0

我剛剛注意到Sixense_init請求兩個參數,但是你沒有調用它。這可能是無法找到該功能的原因。 – Brainbot 2012-07-10 23:00:20

+0

JNI的工作方式是每個本地函數都發送JNIEnv和一個對調用該函數的類的引用以及任何其他參數。 JNI負責發送JNIEnv和它自己的類引用。 – yodal 2012-07-11 02:04:18

4

我找到了答案!看起來,在Windows中使用JNI時,它尋找一個從_Java_開始的函數,而在其他任何平臺上它都會尋找Java_。爲什麼這是這種情況,而不是寫在我不知道的文檔中,但它使一切完美無缺!

+0

那麼你是如何修正它的?改變了dll編譯標誌? – 2012-07-11 18:31:59

+0

當javah創建頭文件時,每個函數都被命名爲'Java_package_Class_method'。奇怪的是,當像這樣編譯時,JNI無法爲本地方法找到正確的函數並吐出錯誤,但是如果在'Java'之前添加了下劃線,那麼JNI將能夠找到該函數。從一開始我就試着用VC++ 2010編譯(我之前使用過MinGW),下劃線在編譯時出現問題。去搞清楚。 – yodal 2012-07-13 16:15:16

+2

領先的下劃線是MSVC的已知stdcall名稱修飾。只要您針對相同的JDK和一個JDK(jni.h是一個關鍵字)進行編譯和使用,就沒有問題。另一方面,MinGW沒有這樣的裝飾,也沒有期待。你可能以某種方式混淆了這兩種環境或調用約定。胡亂猜測。但是破解你創建的頭文件並不是一個解決方案。 「不要編輯這個文件」評論真的有一個原因。 – 2012-07-16 08:58:52

相關問題