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

时间:2012-02-20 20:07:10

标签: java c++ java-native-interface codeblocks unsatisfiedlinkerror

我正在尝试使用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”方法。我在项目和教程之间看到的唯一不同之处是:

  • 我使用的是一个包,而不是默认的包(不应该教程真的这样做吗?!?!来吧让我们专业)
    • 我的回报值。
    • 我在创建它之后移动了我的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:\ _ \包括

5 个答案:

答案 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位于同一目录中)