JNI:在路径上找到了库,但是方法不是(java.lang.UnsatisfiedLinkError)

我正在尝试使用JNI并获取java.lang.UnsatisfiedLinkError。 与其他关于此问题的其他问题不同,我在我的路径上有lib,甚至在删除它时看到exception更改。 我确定我创建的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  #include  JNIEXPORT jint JNICALL Java_com_Tune_add (JNIEnv * env, jobject obj, jint x, jint y) { return x+y; } 

这是我从eclipse获得的运行时exception:

 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) 

我读到上面的exception意味着它DID找到了库“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:\ Program Files( 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:\ _ \包括

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

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

使用两个中的任何一个

gcc -Wl,-kill-at

要么

gcc -Wl,--add-stdcall-alias

这将确保生成Java_com_Tune_add

然后您的方法调用将成功。

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

 #ifdef __cplusplus extern "C" { #endif JNIEXPORT jint JNICALL Java_com_Tune_add ... #ifdef __cplusplus } #endif 

我有同样的问题和标志-Wl,-kill-at为我工作。

尝试使用以下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 "Ph" JNIEXPORT void JNICALL Java_P_f(JNIEnv *env, jclass c, jint i) { printf("%i\n",i); } 

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

设置JAVA_HOME = JDK的路径

set include =%include%;%JAVA_HOME%\ include;%JAVA_HOME%\ include \ win32

步骤7.生成DLL:

cl / LD Pc P.def

步骤8.运行Java程序:

java P.

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