java.lang.UnsatisfiedLinkError – JNI
每次运行程序时,我都会收到java.lang.UnsatisfiedLinkError错误。 我有一个本机,一个包装器,以及通过包装器调用本机的程序。
main.h
#ifndef __MAIN_H__ #define __MAIN_H__ #include #ifdef BUILD_DLL #define DLL_EXPORT __declspec(dllexport) #else #define DLL_EXPORT __declspec(dllimport) #endif #include #include using namespace std; extern "C" { JNIEXPORT void JNICALL native_MessageBox(string text, string title); } #endif
main.cpp中
#include "main.h" #include #include using namespace std; JNIEXPORT void JNICALL MsgBox(string text, string title) { MessageBox(NULL, text.c_str(), title.c_str(), MB_OK); } extern "C" DLL_EXPORT BOOL APIENTRY DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) { switch (fdwReason) { case DLL_PROCESS_ATTACH: break; case DLL_PROCESS_DETACH: break; case DLL_THREAD_ATTACH: break; case DLL_THREAD_DETACH: break; } return TRUE; }
Wrapper.java
public class Wrapper { private static File nativeFile = null; static { //ArchitectureReader and OSReader are classes I made to read the CPU //bits and the OS ArchitectureType archType = ArchitectureReader.getArcitecture(); OSType osType = OSReader.getOS(); String filename = "C:/native-"; if (osType == OSType.Windows) { if (archType == ArchitectureType.BITS_32) filename += "win32"; else if (archType == ArchitectureType.BITS_64) filename += "win64"; else System.exit(1); } else System.exit(1); nativeFile = new File(filename + ".dll"); if (!nativeFile.exists()) System.exit(1); System.load(filename); //This is where the Exception is thrown } private static native void native_MessageBox(String text, String title); public static void MesageBox(String text, String title) { native_MessageBox(text, title); } public static String getNativePath() { return nativeFile.getAbsolutePath(); } }
Main.Java
public class Main { public static void main(String[] args) { Wrapper.MessageBox("Testing JNI", "JNI"); } }
本机是使用MinGW 64位构建的。 无论如何,我不明白为什么我得到错误。 救命?????
我认为问题是你的JNI签名不匹配。 那是:
JNIEXPORT void JNICALL native_MessageBox(string text, string title);
应该是这样的:
JNIEXPORT void JNICALL java_com_example_Wrapper_native_MessageBox(string text, string title);
其中,java_com_example应替换为您的包名(。在包名中替换为_)。
要么
我建议你使用java中提供的javah -jni选项生成你的本机函数签名和声明。
如果你测试
nativeFile = new File(filename + ".dll"); if (!nativeFile.exists()) System.exit(1);
你应该用它!!
System.load(nativeFile);
将本机库加载到正在运行的Java程序有两种不同的方法:
-
System.loadLibrary(String)
和System.load(String)
。 -
System.loadLibrary
方法允许我们从“默认”路径加载库。的System.loadLibrary( “HelloWorld” 的);
-
System.load
允许我们通过其绝对路径从任何地方加载库。
System.load("c:/path/to/dll/HelloWorld.dll")
;
另一件可能导致该错误的原因是在编译我们的cpp库时缺少头文件。 确保在cpp文件中包含标题。