【问题标题】:Getting EXCEPTION_ACCESS_VIOLATION from JVM when trying to access a DLL function尝试访问 DLL 函数时从 JVM 获取 EXCEPTION_ACCESS_VIOLATION
【发布时间】:2019-08-15 01:45:41
【问题描述】:

我试图从我自己创建的 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

【问题讨论】:

  • 您是否使用完全相同编译器编译了所有代码、您的应用程序和 dll?如果没有,那就开始吧。
  • 我使用的是同一个 Java 编译器。将变量 JAVA_HOME 用于 g++ 命令和编译我的 Java 类。困扰我的是我在 g++ 命令“%JAVA_HOME%\include\win32”上看到了这个。我知道第三方 cfint64.dll 应该适用于 64 位机器。我会对此进行更多研究

标签: java c++ dll java-native-interface dynamic-linking


【解决方案1】:

我解决了这个问题。也许我从一开始就没有说清楚,但是我的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);

【讨论】:

    猜你喜欢
    • 2020-06-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-10-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-02-17
    相关资源
    最近更新 更多