来自JNI_CreateJavaVM的异常0xC0000005 (jvm.dll)

我正在使用以下C++代码初始化Java VM。 抛出一个异常,但如果我忽略它,就会失败。JNI_CreateJavaVM0xC0000005

'Jni.exe' (Win32): 已加载 'C:\Tools\Java\Jdk8.77x86\jre\bin\zip.dll'。无法找到或打开 PDB 文件。

在 Jni 中0x02900282引发的异常.exe:0xC0000005:访问冲突读取位置0x00000000。

“Jni.exe” (Win32):已加载“C:\Windows\SysWOW64\shell32.dll”。无法找到或打开 PDB 文件。

我是否忘记了设置或执行某些操作,或者这是“正常”行为?

#include <array>
#include "jni.h"

int main( int argc, char const* args[])
{
    JavaVM* jvm;
    JNIEnv* env;
    
    std::array<JavaVMOption,1> options;
    options[0].optionString = "-Djava.class.path=C:/Users/Thomas/Documents/Visual Studio 2015/Projects/Jni/x64/Debug";
    options[0].extraInfo = nullptr;

    JavaVMInitArgs vm_args;
    vm_args.version = JNI_VERSION_1_8;
    vm_args.options = options.data();
    vm_args.nOptions = options.size();
    vm_args.ignoreUnrecognized = false;

    auto rc = JNI_CreateJavaVM( &jvm, reinterpret_cast<void**>(&env), &vm_args );
    if( rc == JNI_OK )
    {
        jvm->DestroyJavaVM();        
    }
}

这适用于“发布”和“调试”以及 x86 和 x64 生成。


答案 1

JVM主动使用操作系统信号(或Windows术语中的异常)来实现自己的目的:

  • 用于隐式空指针检查和堆栈溢出检查;
  • 用于安全点轮询;
  • 用于远程内存屏障;
  • 等。

SEGV(或异常0xC0000005)也是在JVM启动时故意生成的,以验证某些CPU / OS功能。某些操作系统或虚拟机管理程序存在一个错误,即 AVX 寄存器在信号处理后无法恢复。因此,JVM需要检查情况是否如此(源)。因此,它通过写入零地址来生成异常,然后对其进行处理。

这就是您的情况。是的,这是正常的。


答案 2

这是正常的,就像@apangin说的。如果你想在VisualStudio(2017)中关闭所有0xC0000005例外,你可以这样做:

  1. 异常设置 -Ctrl+Alt+E
  2. 从 Win32 例外下的“0xc0000005访问冲突”中删除勾号

推荐