JNI:在路径上找到库,但没有找到方法 (java.lang.UnsatisfiedLinkError)

发布于 2025-01-07 18:51:47 字数 2301 浏览 1 评论 0原文

我正在尝试使用 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
我的 lala.dll 位于 C:\_\lib

环境变量中:
路径: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:\_\include

I'm trying to use JNI and getting java.lang.UnsatisfiedLinkError. Unlike the other million questions asked about this, I have the lib on my path, and have even seen the exception change when I remove it. I'm sure that something is wrong with the dll I have created, but I'm not sure what.

Here is my java class code:

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

Here is the abridged portion of my javah produced header file:

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

Here is my c++ code:

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

Here is the runtime exception I get from 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)

I read that the above exception means it DID find the library "lala", but that the method "add" is still not defined. The only things I see different between my project and the tutorial are:

  • Mine uses a package, instead of the default package (shouldn't tutorials really do this?!?! come on let's get professional)
    • Mine has a return value.
    • I moved my dll after it was created (I don't think this will break it since my path is configured.)

How is this possible?

Other Info:

OS: Windows 7
JDK: 1.6.0_31 (for x86, 32 bit jvm)
C++ IDE: Code::Blocks (the dll was compiled automatically by the Code::Blocks IDE)
C++ compiler: MinGW32-g++ (the GNU C++ compiler)

I have jni.h and com_Tune.h in C:\_\include
I have lala.dll in C:\_\lib

Environment Variables:
PATH: 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:\_\include

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

吃兔兔 2025-01-14 18:51:47

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

使用两个

gcc -Wl,-kill-at

gcc -Wl,--add 之一-stdcall-alias

这将确保生成 Java_com_Tune_add

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

The problem is with the name compiler has generated: Java_com_Tune_add@16

Use either of two

gcc -Wl,-kill-at

Or

gcc -Wl,--add-stdcall-alias

This will ensure generation of Java_com_Tune_add

And then your method call will be successful.

请帮我爱他 2025-01-14 18:51:47

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

#ifdef __cplusplus
extern "C" {
#endif

JNIEXPORT jint JNICALL Java_com_Tune_add
...

#ifdef __cplusplus
}
#endif

One possible source of the problem might be that you compiled the code using a C++ compiler, which uses a different [calling convention] than plain C. If thats the case then the solution would be to wrap the code for the method in a extern "C" block like this:

#ifdef __cplusplus
extern "C" {
#endif

JNIEXPORT jint JNICALL Java_com_Tune_add
...

#ifdef __cplusplus
}
#endif
旧城烟雨 2025-01-14 18:51:47

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

Just guessing... Is your dll depends on another dll that is not on the path? MinGW modules usually depend on specific C runtime library.

我不在是我 2025-01-14 18:51:47

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

I had the same issue and the flag -Wl,-kill-at worked for me.

左岸枫 2025-01-14 18:51:47

尝试使用以下 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命令中promt,定义以下变量:

set 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位于同一目录下)

Try with following example for Windows:
(remember that the Java class name must be the same that corresponding file name)

Step 1. Create the following Java file (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);
  }
}

Step 2. javac P.java

Step 3. javah P

Then, "javah" generates the header file "P.h"

Step 4. Create the file "P.def" including the following two lines (this file defines the exported symbols, in this case the name of C function):

EXPORTS
Java_P_f

Step 5. Create your C file (P.c):

#include "P.h"

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

Step 6. Within Visual Studio command promt, define the following variables:

set JAVA_HOME= the path of JDK

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

Step 7. Generate DLL:

cl /LD P.c P.def

Step 8. Run the Java program:

java P

(Note: P.dll and P.class are located in the same directory)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文