java 调用原生方法时返回java.lang.UnsatisfiedLinkError

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/11420153/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-31 05:02:46  来源:igfitidea点击:

java.lang.UnsatisfiedLinkError returned when calling native method

javadlljava-native-interface

提问by yodal

I am trying to make a Java wrapper for a third party DLL. I created my own DLL that acts as a middle man between JNI and the third party DLL. In java I load this DLL fine but the error java.lang.UnsatisfiedLinkError: sixense.Sixense.init()Zis returned. What could be causing this error and how can I debug it properly?

我正在尝试为第三方 DLL 制作 Java 包装器。我创建了自己的 DLL,充当 JNI 和第三方 DLL 之间的中间人。在 java 中,我很好地加载了这个 DLL,但java.lang.UnsatisfiedLinkError: sixense.Sixense.init()Z返回了错误。什么可能导致此错误以及如何正确调试它?

Main.java:

主.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:

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");
    }
}

An excerpt from sixense_Sixense.cpp:

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;
}

An excerpt from sixense_Sixense.h:

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);

Output from 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 Java_sixense_Sixense_autoEnableHemisphereTracking@12
          2    1 000011A0 Java_sixense_Sixense_exit@8
          3    2 00001A40 Java_sixense_Sixense_getAllData@16
          4    3 000019A0 Java_sixense_Sixense_getAllNewestData@12
          5    4 00001DC0 Java_sixense_Sixense_getColorBase@12
          6    5 00001B30 Java_sixense_Sixense_getData@20
          7    6 00001BD0 Java_sixense_Sixense_getFilterEnabled@8
          8    7 00001C40 Java_sixense_Sixense_getFilterParams@12
          9    8 00001D60 Java_sixense_Sixense_getHighPriorityBinding@8
         10    9 00001B90 Java_sixense_Sixense_getHistorySize@8
         11    A 000011C0 Java_sixense_Sixense_getMaxBases@8
         12    B 00001210 Java_sixense_Sixense_getMaxControllers@8
         13    C 00001AE0 Java_sixense_Sixense_getNewestData@16
         14    D 00001220 Java_sixense_Sixense_getNumActiveControllers@8
         15    E 00001180 Java_sixense_Sixense_init@8
         16    F 000011F0 Java_sixense_Sixense_isBaseConnected@12
         17   10 00001230 Java_sixense_Sixense_isControllerEnabled@12
         18   11 000011D0 Java_sixense_Sixense_setActiveBase@12
         19   12 00001D90 Java_sixense_Sixense_setBaseColor@20
         20   13 00001BA0 Java_sixense_Sixense_setFilterEnabled@12
         21   14 00001C00 Java_sixense_Sixense_setFilterParams@24
         22   15 00001D30 Java_sixense_Sixense_setHighPriorityBinding@12
         23   16 00001CE0 Java_sixense_Sixense_triggerVibration@20

  Summary

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

回答by RudolfW

When calling a native function in Java, the runtime tries to use:

在 Java 中调用本机函数时,运行时会尝试使用:

  • a stdcall-style decorated function: _functionName@n, where n is the number of bytes in the parameter list,
  • and a cdecl-style undecorated function: functionName.
  • 一个 stdcall 风格的装饰函数:_functionName@n,其中 n 是参数列表中的字节数,
  • 和 cdecl 风格的未修饰函数:functionName.

When compiling with MinGW, you will get a mix of these two: MinGW will append the @n, but will not prepend the underscore: functionName@n.

使用 MinGW 进行编译时,您将获得这两者的混合:MinGW 将附加@n,但不会预先添加下划线:functionName@n

The way to solve this is to tell ldnot to add the suffix, using the --kill-atswitch (or -Wl,--kill-atif you call it through GCC).

解决这个问题的方法是告诉ld不要添加后缀,使用--kill-at开关(或者-Wl,--kill-at如果你通过 GCC 调用它)。

回答by yodal

I have found the answer! It seems that when using JNI in Windows it looks for a function starting with _Java_while in every other platform it looks for Java_. Why this is the case and not written in the documentation I don't know but it make everything work perfectly!

我找到了答案!似乎在 Windows 中使用 JNI 时,它会在它寻找的_Java_所有其他平台中查找以while开头的函数Java_。为什么会这样,而不是写在文档中我不知道,但它使一切正常!

回答by Brainbot

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

Looks like Java cant find the library, did you put it in the right place?

看起来Java找不到库,你把它放在正确的地方了吗?

You might need to change the java.library.path, take a look at this.

你可能需要改变java.library.path,看看这个

If you want to print the contents of it use:

如果要打印它的内容,请使用:

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

This might print a lot, you might want to split(";")and print each entry on its own.

这可能会打印很多,您可能希望自己split(";")打印每个条目。