另一个与JNI相关的java.lang.UnsisfiedLinkError
Yet another JNI related java.lang.UnsatisfiedLinkError
我看过很多关于类似问题的论坛帖子,但我觉得我都看到了。简言之,我通过Java访问了JNI的奇妙之处,获得了本机代码。在我开始使用JAVA软件包之前,代码运行良好。我关注了所有关于确保Javah cmd在正确文件夹中运行的论坛帖子,并成功构建了我的DLL。我已经确保包装器所在的包存在于C++函数的名称中。由于项目的规模,我将简单地展示这段代码的一个示例。注意,所有代码(DLL、JVM C++编译器(都以32位运行,目标是运行windows 8.1的PC。
我所有的Java代码都包含在包中:
package com.optin.executableContainer.client;
因此,在我的Java包装器类中,我按照如下明确地加载DLL(32位(
static
{
System.load("C:\JNITests\JNIBridge.dll");
}
我知道这加载DLL,因为在该文件夹中没有DLL。我得到"无法加载库"运行时错误。使用的头代码是由javah-jni命令生成的
JNIEXPORT void JNICALL Java_com_optin_executableContainer_client_COMControl_setControlBackColor
(JNIEnv *, jobject, jlong);
.cpp文件中包含的关联C++代码是:
JNIEXPORT void JNICALL Java_com_optin_executableContainer_client_COMControl_setControlBackColor
(JNIEnv *env, jobject obj, jlong color)
{
printf("nHello Worldn");
}
使用Visual Studio 2010编译此文件时没有任何错误。我已经通过使用DLL导出查看器验证了该函数存在于目标DLL中,该查看器将函数名称显示为:
void __stdcall Java_com_optin_executableContainer_client_COMControl_setControlBackColor(struct JNIEnv_ *,class _jobject *,__int64)
然而,当我在Eclipse IDE中运行这段代码时,我会得到可怕的
Exception in thread "main" java.lang.UnsatisfiedLinkError:
com.optin.executableContainer.client.COMControl.setControlBackColor(J)V
at com.optin.executableContainer.client.COMControl.setControlBackColor(Native Method)
如果我一路上错过了什么,请向我指出。
问候Jarren
更新:我去比较了工作中的dll(在打包之前完成(和新的dll,发现了一些主要的差异。这是未打包的工作dll 的函数名
_Java_COMControl_destroy@8
这是新打包的、无法运行的dll 的函数名
void __stdcall Java_com_optin_executableContainer_client_COMControl_destroy(struct JNIEnv_ *,class _jobject *)
Java代码COMControl.java
(产生COMControl头(如下所示声明该函数
private native void destroy();
我尝试比较产生工作文件和产生损坏文件的头文件之间的差异,除了明显的基于打包的更改(com_optin等(之外,没有其他差异。COMControl.java
文件中唯一的区别是在Java文件的顶部包含了package com.optin.executableContainer.client;
。
这是怎么回事?
您正在将本机例程导出为名称损坏的C++
函数。我们之所以能说出这一点,是因为函数的参数列在库的导出信息中。只要您能够告知以函数名称传递的参数的类型,就意味着该函数将作为装饰的C++
方法导出。如果您查看库的原始导出信息而不进行解映射,则它看起来像:
?Java_Package_ComControl_destroy@@YGXPAUJNIEnv_@@PAV_jobject@@@Z
当它看起来像这样时,java运行时找不到它,它应该看起来更像:
_Java_Package_ComControl_destroy@8
其是未修饰的CCD_ 6例程。@8
是stdcall的简写,表示在堆栈中传递给例程的8个字节
发生这种情况的最常见原因是声明函数并由javah生成的.h
文件与定义函数内容的.cpp
文件不匹配,即.h
文件和.cpp
文件之间存在一些细微的差异。您应该将.h
文件中的函数声明复制粘贴到.cpp
文件中,确保所有参数和所有类型对齐。
此外,对于.cpp
文件,您必须确保它#include
是由javah生成的.h
文件,而不仅仅是#include <jni.h>
。如果不这样做,编译器将不知道该例程将被导出为C
样式的例程。这是生成的编译dll不包含该方法的未处理版本的常见原因。
如果您想使用未修饰的C
调用约定手动强制导出例程,在.cpp
文件中的函数定义中,您可以放入:
extern "C"
JNIEXPORT void JNICALL
Java_com_optin_executableContainer_client_COMControl_setControlBackColor
(JNIEnv *env, jobject obj, jlong color)
{
printf("nHello Worldn");
}
通过以这种方式使用extern "C"
,函数将被定义为C
例程而不是C++
例程进行导出;但这是不可取的,因为您实际上应该包括来自javah
的.h
。
我不知道visual studio是否有类似于gcc
的-Wmissing-declarations
,它会注意到这样的不一致性,这对.dll
s有点重要。
- java.lang.IndexOutOfBoundsException with JNA
- Android Studio 3.1.2 - 无法运行C++子例程"No implementation found for Java.lang.String..."
- java.lang.UnsatisfiedLinkError: Abc.greetings()V
- java.lang.Field 等效于 c++ 中
- 为什么日食总是发生错误"An internal error occurred during: "通知选择侦听器". java.lang.StackOverflowError"
- java.lang.UnsatisfiedLinkError:未找到实现
- JNI GetMethodID 调用,带有挂起的异常 java.lang.ClassNotFoundException
- java.lang.UnsatisfiedLinkError: dlopen failed: 无法加载"libPrivateSsl.so"所需的库"libcrypto.so.1.0.0";
- 单元测试环境中的"java.lang.UnsatisfiedLinkError: *.so: Can't find dependent libraries"
- JNI 代码返回字符串,但得到错误 java.lang.UnsatisfiedLinkError: com.packag
- 如何在没有System32的情况下解决"java.lang.UnsatisfiedLinkError:找不到依
- JNA从DLL调用C++对象-java.lang.IollegalArgumentException:Structure
- 线程中的异常 "main" java.lang.UnsatisfiedLinkError: no JNTIest in java.library.path
- jni java.lang.unsatisfiedlinkerror,无法链接方法
- 从WordCount Hadoop示例调用Helloworld Jni函数,给出错误Java.lang.unsatisf
- 在hadoop 2.7.4的自定义排序类中调用C函数,给出Java.lang.unsatisfiedlinkerror
- 在运行时获得Java.lang.unsatisfiedlinkerror
- AndroidRuntime: java.lang.UnsatisfiedLinkError: Native metho
- 线程"main" java.lang.UnsatisfiedLinkError: Native.initiate(I)V 从 Java 运行本机 dll 时
- JNI : 线程"AWT-EventQueue-0" java.lang.UnsatisfiedLinkError 中的异常