使用 dlopen 在 Mac 上加载 libjvm.dylib 时发出信号 SIGSEGV

Signal SIGSEGV when loading libjvm.dylib on Mac using dlopen

本文关键字:信号 SIGSEGV dylib libjvm dlopen Mac 加载 使用      更新时间:2023-10-16

我正在尝试从Mac中的libjvm.dylib获取指向JNI_CReateJVM正确的函数指针。窗口中的对应项正在工作。因此,指向libjvm.dylib(m_jvm_dll(的指针不为空,即库的路径是正确的。此外,m_createJVM_Ptr也不是空的。所以我肯定会得到指示。但是一旦我使用m_createJVM_Ptr以下Thread1:signal SIGSEGV错误就会出现在Xcode中:

->  0x11566c2b4: movl   (%rsi), %eax
0x11566c2b6: leaq   0xf8(%rbp), %rsi
0x11566c2bd: vmovdqu %ymm0, (%rsi)
0x11566c2c1: vmovdqu %ymm7, 0x20(%rsi)
0x11566c2c6: vmovdqu %ymm8, 0x40(%rsi)
0x11566c2cb: vmovdqu %ymm15, 0x60(%rsi)

这是罪魁祸首函数。

bool JVMInitializer::create_JVM(SettingDlg* inp_settingDlg){
wxString jvm_path;
wxString ij_path;
wxString bioformats_path;
//if (inp_settingDlg)
//{
//  jvm_path = inp_settingDlg->getJVMPath();
//  ij_path = inp_settingDlg->getIJPath();
//  bioformats_path = inp_settingDlg->getBioformatsPath();
//}
//Loading JVM library and methods.
jvm_path = "/Users/dev/Downloads/ImageJ/jre/lib/server/libjvm.dylib";
#ifdef _WIN32
m_jvm_dll = LoadLibraryW(jvm_path.ToStdWstring().c_str());
#else
m_jvm_dll = dlopen((const char*)jvm_path.mb_str(wxConvUTF8), RTLD_NOW);
#endif
if (m_jvm_dll == nullptr)
    return false;
#ifdef _WIN32
m_createJVM_Ptr = (decltype(&JNI_CreateJavaVM))GetProcAddress(m_jvm_dll, "JNI_CreateJavaVM");
#else
m_createJVM_Ptr = (CreateJavaVM_t*) dlsym(m_jvm_dll, "JNI_CreateJavaVM");
#endif
if (m_createJVM_Ptr == nullptr)
  return false;
using namespace std;    
JavaVMOption* options = new JavaVMOption[1];
//Geting absolute path to class file.
wxString exePath = wxStandardPaths::Get().GetExecutablePath();
exePath = wxPathOnly(exePath);
string imageJPath = "-Djava.class.path=" + exePath + GETSLASH() + "Java_Code" + GETSLASH() + getPathSeparator();
//imageJPath.append(ij_path + getPathSeparator());
//imageJPath.append(bioformats_path);
imageJPath.append(exePath + GETSLASH() + "Java_Code" + GETSLASH() + "ij.jar;");
imageJPath.append(exePath + GETSLASH() + "Java_Code" + GETSLASH() + "SlideBook6Reader.jar;");
imageJPath.append(exePath + GETSLASH() + "Java_Code" + GETSLASH() + "bioformats_package.jar;");
options[0].optionString = const_cast<char*>(imageJPath.c_str());
m_VMargs.version = JNI_VERSION_1_6;             // minimum Java version
m_VMargs.nOptions = 1;                          // number of options
m_VMargs.options = options;
m_VMargs.ignoreUnrecognized = false;     // invalid options make the JVM init fail
jint rc = m_createJVM_Ptr(&m_pJvm, (void**)&m_pEnv, &m_VMargs);
delete[] options;
if (rc != JNI_OK) {
    return false;
}
return true;
}

故障发生在 jint rc = .....(倒数第 7 行(。

以下是源文件的链接: JVM 初始值设定项.cpp JVMINITIALIZER.h

所以我在没有动态加载 jvm 库的情况下运行了代码,它通过直接调用 JNI_CreateJavaVM 方法工作,但我希望它适用于动态加载。另外需要注意的一点是,我在imageJ中使用JRE进行Java 1.8附带的动态加载。认为此信息可能是相关的。

JNI_CreateJavaVM(( 有意引发(并捕获(访问冲突异常。

调试器(Visual Studio、XCode 等(通常会在引发此异常时停止。

可以将调试器配置为在引发访问冲突异常时不停止,或者忽略此异常并继续执行:

Visual Studio:按"继续"。

XCode:进入调试器窗口:pr h -s false SIGSEGV,然后按"继续"。