我正在尝试编写一个简单的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相同的目录中
答案 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)
你需要