在尝试访问 DLL 函数时从 JVM 获取EXCEPTION_ACCESS_VIOLATION
Getting EXCEPTION_ACCESS_VIOLATION from JVM when trying to access a DLL function
我正在尝试从我创建自己的DLL文件访问第三方DLL,但是在使用JNI调用我自己的DLL时遇到JVM内存访问冲突。
我试图调用的第三方 dll 是 cfint64.dll。 对于兼容性问题,我正在创建自己的dll来访问第三方dll。
我不知道第三方 cfint64.dll 使用了什么编译器,但它应该用于 64 位机器。
就我而言,这就是我创建自己的DLL的方式:g++ -I"%JAVA_HOME%\include" -I"%JAVA_HOME%\include\win32" -shared -o dll3minterface.dll DLL3MInterface.cpp
我知道第三方dll具有以下函数签名:
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class dllCommunication */
#ifndef _Included_dllCommunication
#define _Included_dllCommunication
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: dllCommunication
* Method: nJavaInitInstance
* Signature: (Ljava/lang/String;)I
*/
JNIEXPORT jint JNICALL Java_dllCommunication_nJavaInitInstance
(JNIEnv *, jobject, jstring);
#ifdef __cplusplus
}
#endif
#endif
我创建的头文件如下:
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_artificialmedgui_coderdx_DLL3MInterface */
#ifndef _Included_com_artificialmedgui_coderdx_DLL3MInterface
#define _Included_com_artificialmedgui_coderdx_DLL3MInterface
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: com_artificialmedgui_coderdx_DLL3MInterface
* Method: nJavaInitInstance
* Signature: (Ljava/lang/String;)I
*/
JNIEXPORT jint JNICALL Java_com_artificialmedgui_coderdx_DLL3MInterface_nJavaInitInstance(JNIEnv *, jobject, jstring);
#ifdef __cplusplus
}
#endif
#endif
导致内存访问冲突的.cpp文件如下。请注意,导致错误的行是funcCall(inJNIStr);。 如果我注释掉这个函数调用,程序结束没有错误。
#include <windows.h>
#include <jni.h> // JNI header provided by JDK
#include <iostream> // C++ standard IO header
#include "com_artificialmedgui_coderdx_DLL3MInterface.h" // Generated
using namespace std;
typedef int (__stdcall* initInstanceFunc)(jstring);
JNIEXPORT jint JNICALL Java_com_artificialmedgui_coderdx_DLL3MInterface_nJavaInitInstance(JNIEnv *env, jobject, jstring inJNIStr) {
// Step 1: Convert the JNI String (jstring) into C-String (char*)
const char *inCStr = env->GetStringUTFChars(inJNIStr, NULL);
HINSTANCE hGetProcIDDLL = LoadLibrary("C:\workspace\AMI3MDLLInterface\resources\cfint64.dll");
if (!hGetProcIDDLL) {
std::cout << "could not load the dynamic library" << std::endl;
return EXIT_FAILURE;
}
else{
std::cout << "Loaded cfint64.dll library!!!!" << std::endl;
}
// resolve function address here
initInstanceFunc funcCall = (initInstanceFunc)GetProcAddress(hGetProcIDDLL, "Java_dllCommunication_nJavaInitInstance");
if (*funcCall != NULL) {
funcCall(inJNIStr);
}
else{
std::cout << "Function is invalid" << std::endl;
}
return 1; //Testing
}
我能够加载第三方 cfint64.dll但是当调用它的函数之一时,例如 funcCall(inJNIStr);它会抛出错误。
也许我在调用 cfint64.dll 函数时没有从我的.cpp文件中传递正确的字符串数据类型? 我不是一个C++程序员,所以任何导致问题的想法都值得赞赏。
#
# A fatal error has been detected by the Java Runtime Environment:
#
# EXCEPTION_ACCESS_VIOLATION (0xc0000005) at pc=0x0000000000000000, pid=12276, tid=11080
#
# JRE version: Java(TM) SE Runtime Environment (10.0.1+10) (build 10.0.1+10)
# Java VM: Java HotSpot(TM) 64-Bit Server VM (10.0.1+10, mixed mode, tiered, compressed oops, g1 gc, windows-amd64)
# Problematic frame:
# C 0x0000000000000000
#
# No core dump will be written. Minidumps are not enabled by default on client versions of Windows
#
# If you would like to submit a bug report, please visit:
# http://bugreport.java.com/bugreport/crash.jsp
# The crash happened outside the Java Virtual Machine in native code.
# See problematic frame for where to report the bug.
#
--------------- S U M M A R Y ------------
Command Line: com.artificialmedgui.coderdx.DLL3MInterface
Host: Intel(R) Core(TM) i7-4720HQ CPU @ 2.60GHz, 8 cores, 15G, Windows 10 , 64 bit Build 17134 (10.0.17134.648)
Time: Sun Mar 24 14:15:30 2019 Eastern Daylight Time elapsed time: 1 seconds (0d 0h 0m 1s)
--------------- T H R E A D ---------------
Current thread (0x000001421b910800): JavaThread "main" [_thread_in_native, id=11080, stack(0x0000003371700000,0x0000003371800000)]
Stack: [0x0000003371700000,0x0000003371800000], sp=0x00000033717ff258, free space=1020k
Native frames: (J=compiled Java code, j=interpreted, Vv=VM code, C=native code)
Java frames: (J=compiled Java code, j=interpreted, Vv=VM code)
j com.artificialmedgui.coderdx.DLL3MInterface.nJavaInitInstance(Ljava/lang/String;)I+0
j com.artificialmedgui.coderdx.DLL3MInterface.main([Ljava/lang/String;)V+17
v ~StubRoutines::call_stub
siginfo: EXCEPTION_ACCESS_VIOLATION (0xc0000005), data execution prevention violation at address 0x0000000000000000
Register to memory mapping:
RIP=0x0000000000000000 is an unknown value
RAX=0x00000006d0a4b6c0 is an oop
java.lang.String
{0x00000006d0a4b6c0} - klass: 'java/lang/String'
RBX={method} {0x000001423eb204a8} 'nJavaInitInstance' '(Ljava/lang/String;)I' in 'com/artificialmedgui/coderdx/DLL3MInterface'
RCX=0x00000033717ff380 is pointing into the stack for thread: 0x000001421b910800
RDX=0x0000000000000002 is an unknown value
RSP=0x00000033717ff258 is pointing into the stack for thread: 0x000001421b910800
RBP=0x00000033717ff2d0 is pointing into the stack for thread: 0x000001421b910800
RSI=0x0000000000000002 is an unknown value
RDI=0x00000033717ff380 is pointing into the stack for thread: 0x000001421b910800
R8 =0x0000000000000000 is an unknown value
R9 =0x0000000000000000 is an unknown value
R10=0x0000000000000002 is an unknown value
R11=0x00000033717fef80 is pointing into the stack for thread: 0x000001421b910800
R12=0x0000000000000000 is an unknown value
R13={method} {0x000001423eb204a8} 'nJavaInitInstance' '(Ljava/lang/String;)I' in 'com/artificialmedgui/coderdx/DLL3MInterface'
R14=0x00000033717ff388 is pointing into the stack for thread: 0x000001421b910800
R15=0x000001421b910800 is a thread
我解决了这个问题。 也许我从一开始就没有说清楚,但我的 JNI DLL 正在调用另一个第三方 JNI DLL。 因此,当您从 Java 代码调用 JNI DLL 时,您只需要传递实际参数。 我想JVM链接器会在调用实际DLL函数时添加其他参数。 无论如何,从我的DLL中,我只需要传递JVM链接器可能会传递的这些附加参数。
要调用第二个 JNI DLL 函数,请执行以下操作:
Wrong:
typedef int (__stdcall* initInstanceFunc)(jstring);
Works:
typedef int (__stdcall* initInstanceFunc)(JNIEnv*,jobject,jstring);
...
funcCall(env,obj,inJNIStr);
- C++为构建时间获取QDateTime的可靠方法
- lambda参数转换为constexpr技巧,然后获取带链接的数组
- 如何使用 < 和 > 命令获取 c++ 中的输入和输出?
- 使用指针从C++中的数组中获取最大值
- 如何获取std::result_of函数的返回类型
- 如何在openssl-ecc中获取十六进制格式的私钥
- 使用Unreal C++获取VR耳机的世界位置/方向
- 获取日期异步信号安全吗?如果在信号处理程序中使用,它会导致死锁吗
- 从C字符串中获取奇怪的字符串长度
- 为什么我的for循环不能正确获取argv
- 从python中调用C++函数并获取返回值
- 如何获取一个数字的前3位
- 获取字符串的长度并将其分配给数组
- 无法获取菜单选择以运行函数.C++
- 数组长度,为什么从命令行获取时不能使用它?
- Boost Spirit,获取迭代器内部语义动作
- 尝试通过OCI例程从Oracle获取blob数据,但出现错误:ORA-01008:并非所有变量都绑定
- 正在从jvm.dll获取FindClass函数指针
- 在尝试访问 DLL 函数时从 JVM 获取EXCEPTION_ACCESS_VIOLATION
- 如何使用c++语言以编程方式获取已安装的所有Java JRE(JVM)及其路径