JNI:UnsatisfiedLinkError:找不到依赖库

时间:2012-08-26 05:09:51

标签: java java-native-interface

我正在尝试编写一个简单的Java程序,通过JNI调用C函数来打印“Hello World”。一切都没有错误编译,但是当我运行程序时,我得到一个“UnsatisfiedLinkError:找不到依赖库”。

根据Dependency Walker和dumpbin,唯一的依赖是“kernel32.dll”,在C:\ Windows \ System32及其依赖项中,也在System32中。

调用

    System.loadLibrary("Kernel32");

返回时没有错误,但加载包含打印功能的Hello.dll仍会引发错误。

有谁知道造成这种情况的原因是什么?

编辑:

Dependency Walker确实提供了两个警告/错误:

-Error:由于隐式依赖模块中缺少导出功能,至少有一个模块具有未解析的导入。

-Error:找到了具有不同CPU类型的模块。

编辑:

以下是一些更多细节:我正在运行Windows 7 64位,并使用cl编译我的.dll(Visual Studio 2010)。

我的Java代码Hello.java:

    public class Hello
    {
        public static native void hello();

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

        static
        {
            // Extra dependencies load with no error
            System.loadLibrary("NTDLL");
            System.loadLibrary("KERNELBASE");
            System.loadLibrary("KERNEL32");
            System.loadLibrary("Hello"); // Throws UnsatisfiedLinkError
        }
    }

我可以编译没有错误的java文件,并使用javah -jni生成一个C头Hello.h:

    /* DO NOT EDIT THIS FILE - it is machine generated */
    #include <jni.h>
    /* Header for class Hello */

    #ifndef _Included_Hello
    #define _Included_Hello
    #ifdef __cplusplus
    extern "C" {
    #endif
    /*
     * Class:     Hello
     * Method:    hello
     * Signature: ()V
     */
    JNIEXPORT void JNICALL Java_Hello_hello
      (JNIEnv *, jclass);

    #ifdef __cplusplus
    }
    #endif
    #endif

我在Hello.c中实现了标头:

    #include <stdio.h>
    #include <jni.h>
    #include "Hello.h"
    #pragma comment(linker, "/EXPORT:Java_Hello_hello=_Java_Hello_hello@8")

    JNIEXPORT void JNICALL
    Java_Hello_hello(JNIEnv* env, jclass class)
    {
        printf("Hello World\n");
        return;
    }

C代码是用cl编译的(尽管我也尝试过tcc)到Hello.dll中,它存放在与java .class相同的目录中

3 个答案:

答案 0 :(得分:2)

看起来我的问题是64位系统和java安装以及32位C编译器的组合。

默认情况下,Visual C ++ cl编译器会生成32位应用程序,这会在64位java加载时导致错误。我使用Windows SDK 7.1 64位编译器编译了我的应用程序,它运行时没有错误,并且删除了Dependency Walker中的警告。

答案 1 :(得分:1)

我试图让JNI为学校的最终项目工作,并在经过一个月的头撞之后最终寻找替代方案。请尝试使用Java Native Access。它允许您从Windows(.dll)和Linux(.so)上的任何共享库调用任何C函数,它甚至为某些Win32函数提供了便利方法。将您的本机代码编译为共享库,然后使用JNA动态链接到库并调用您的函数。它说它明显慢于JNI,这是有道理的,因为一切都是动态加载的,但我注意到没有性能命中。

要弄清楚C编译器如何破坏你的函数名称 - 将strlen转换为_strlen@4或其他东西 - 我建议DLL Export Viewer(下载链接靠近底部)。我不知道Linux是否有类似的工具。

答案 2 :(得分:0)

你需要

  • 将您的DLL放到windows \ system32 \文件夹
  • 在命令行中指定java.library.path