6

我正在尝试使用 JNI 并获取 java.lang.UnsatisfiedLinkError。与其他有关此问题的数百万个问题不同,我的路径上有这个库,甚至在我删除它时也看到了异常变化。我确定我创建的 dll 有问题,但我不确定是什么。

这是我的java类代码:

package com;

public class Tune {
    static {
        System.loadLibrary("lala");
    }
    public static void main(String[] args) {
        Tune j = new Tune();
        System.out.println("2+6="+j.add(2, 6));
    }
    native public int add(int x,int y);
}

这是我的 javah 生成的头文件的删节部分:

/*
 * Class:     com_Tune
 * Method:    add
 * Signature: (II)I
 */
JNIEXPORT jint JNICALL Java_com_Tune_add
  (JNIEnv *, jobject, jint, jint);

这是我的 C++ 代码:

#include <jni.h>
#include <com_Tune.h>

JNIEXPORT jint JNICALL Java_com_Tune_add
  (JNIEnv * env, jobject obj, jint x, jint y) {
    return x+y;
  }

这是我从 eclipse 得到的运行时异常:

Exception in thread "main" java.lang.UnsatisfiedLinkError: com.Tune.add(II)I
    at com.Tune.add(Native Method)
    at com.Tune.main(Tune.java:9)

我读到上面的异常意味着它确实找到了库“lala”,但是仍然没有定义方法“add”。我认为我的项目和教程之间的唯一不同之处是:

  • 我的使用一个包,而不是默认包(教程不应该真的这样做吗?!?!来吧,让我们变得专业)
    • 我的有一个返回值。
    • 我在创建 dll 后移动了它(我认为这不会破坏它,因为我的路径已配置。)

这怎么可能?

其他信息:

操作系统:Windows 7
JDK:1.6.0_31(用于 x86,32 位 jvm)
C++ IDE:Code::Blocks(DLL 由 Code::Blocks IDE 自动编译)
C++ 编译器:MinGW32-g++(GNU C++ 编译器)

我在 C:\_\include 中有 jni.h 和 com_Tune.h
我在 C:\_\lib 中有 lala.dll

环境变量:
路径:C:\Program Files (x86)\NVIDIA Corporation\PhysX\Common;%CommonProgramFiles%\Microsoft Shared\Windows Live;C:\Program Files (x86)\AMD APP\bin\x86_64;C:\程序文件 (x86)\AMD APP\bin\x86;%SystemRoot%\system32;%SystemRoot%;%SystemRoot%\System32\Wbem;%SYSTEMROOT%\System32\WindowsPowerShell\v1.0\;C:\Program Files ( x86)\ATI Technologies\ATI.ACE\Core-Static;C:\Apps;%JAVA_HOME%\bin;C:\Program Files\MySQL\MySQL Server 5.5\bin;%MAVEN_HOME%\bin;%HADOOP_INSTALL%\bin ;c:\Program Files (x86)\Microsoft SQL Server\100\Tools\Binn\;c:\Program Files\Microsoft SQL Server\100\Tools\Binn\;c:\Program Files\Microsoft SQL Server\100\ DTS\Binn\;C:\MinGW\bin;C:\Program Files (x86)\GnuWin32\bin;C:_\path;C:\_\lib;C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\bin;C:\_\包括

4

5 回答 5

4

问题在于编译器生成的名称:Java_com_Tune_add@16

使用两个中的任何一个

gcc -Wl,-kill-at

或者

gcc -Wl,--add-stdcall-alias

这将确保生成 Java_com_Tune_add

然后你的方法调用就会成功。

于 2012-10-03T11:40:12.530 回答
2

问题的一个可能来源可能是您使用 C++ 编译器编译代码,该编译器使用与普通 C 不同的[调用约定]。如果是这种情况,那么解决方案是将方法的代码包装在一个extern "C"块中,如这个:

#ifdef __cplusplus
extern "C" {
#endif

JNIEXPORT jint JNICALL Java_com_Tune_add
...

#ifdef __cplusplus
}
#endif
于 2012-02-20T20:19:10.690 回答
1

只是猜测...您的 dll 是否依赖于不在路径上的另一个 dll?MinGW 模块通常依赖于特定的 C 运行时库。

于 2012-02-20T20:44:47.760 回答
0

尝试以下 Windows 示例:(记住 Java 类名必须与相应的文件名相同)

步骤 1. 创建以下 Java 文件 (P.java):

class P
{
  static
  {
    // "P" is the name of DLL without ".dll"
    System.loadLibrary ("P");
  }

  public static native void f(int i);

  public static void main(String[] args)
  {
    f(1);
  }
}

步骤 2.javac P.java

步骤 3.javah P

然后,“javah”生成头文件“Ph”

步骤 4. 创建文件“P.def”,包括以下两行(此文件定义导出的符号,在本例中为 C 函数的名称):

EXPORTS
Java_P_f

第 5 步。创建您的 C 文件 (Pc):

#include "P.h"

JNIEXPORT void JNICALL Java_P_f(JNIEnv *env, jclass c, jint i)
{
  printf("%i\n",i);
}

步骤 6. 在 Visual Studio 命令提示符中,定义以下变量:

设置 JAVA_HOME= JDK的路径

设置包含=%include%;%JAVA_HOME%\include;%JAVA_HOME%\include\win32

步骤 7. 生成 DLL:

cl /LD Pc P.def

步骤 8. 运行 Java 程序:

爪哇

(注:P.dll 和 P.class 位于同一目录下)

于 2013-11-26T16:35:55.227 回答
0

我遇到了同样的问题,标志 -Wl,-kill-at 对我有用。

于 2013-07-18T12:36:22.367 回答