我正在尝试使用JNI并获取java.lang.UnsatisfiedLinkError。与其他关于此问题的其他百万问题不同,我在我的路径上有lib,甚至在我删除它时看到异常更改。我确定我创建的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)
我读到上面的异常意味着它DID找到了库“lala”,但是仍然没有定义“add”方法。我在项目和教程之间看到的唯一不同之处是:
这怎么可能?
操作系统: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:\ _ \包括
答案 0 :(得分:4)
问题在于编译器生成的名称:Java_com_Tune_add@16
使用两个中的任何一个
gcc -Wl,-kill-at
或
gcc -Wl,--add-stdcall-alias
这将确保生成Java_com_Tune_add
然后您的方法调用将成功。
答案 1 :(得分:2)
问题的一个可能的来源可能是您使用C ++编译器编译代码,该编译器使用与普通C不同的[调用约定]。如果是这种情况,则解决方案是将方法的代码包装在这样的extern "C"
块:
#ifdef __cplusplus
extern "C" {
#endif
JNIEXPORT jint JNICALL Java_com_Tune_add
...
#ifdef __cplusplus
}
#endif
答案 2 :(得分:1)
猜猜......你的dll是否依赖于另一个不在路上的dll? MinGW模块通常依赖于特定的C运行时库。
答案 3 :(得分:0)
我有同样的问题,标志-Wl,-kill-at为我工作。
答案 4 :(得分: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”生成头文件“P.h”
步骤4.创建文件“P.def”,包括以下两行(此文件定义导出的符号,在本例中为C函数的名称):
EXPORTS
Java_P_f
步骤5.创建C文件(P.c):
#include "P.h"
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 P.c P.def
步骤8.运行Java程序:
java P
(注意:P.dll和P.class位于同一目录中)