在 Linux 上,JNI AttachNativeThread 总是失败,返回值为 -1

JNI AttachNativeThread always fails with -1 return value on Linux

本文关键字:返回值 失败 AttachNativeThread Linux JNI      更新时间:2023-10-16

我正在围绕本机C++库编写JNI包装器,但是在将本机线程附加到Linux上的JVM时遇到问题。在Windows上一切正常,但是当我在Ubuntu机器上调用AttachNativeThread((时,它总是返回-1。

这是我获得 JNIEnv 指针的方式:

JNIEnv* Utils::getJNI() {
    JNIEnv* jni;
    int getEnvResult = FMODWrapper::jvm->GetEnv((void**) &jni, JNI_VERSION_1_8);
    if (getEnvResult == JNI_EDETACHED) {
        JavaVMAttachArgs attachArgs;
        attachArgs.version = JNI_VERSION_1_8;
        attachArgs.group = nullptr;
        std::stringstream newName;
        newName << "jni-attached-daemon-" << std::this_thread::get_id();
        attachArgs.name = (char*) newName.str().c_str();
        int attachResult = FMODWrapper::jvm->AttachCurrentThreadAsDaemon(ANDROID_VOIDPP_CAST &jni, &attachArgs);
        if(attachResult != 0) {
            std::cerr << "Failed to attach thread! " << attachResult << "(" << newName.str() << ")" << std::endl;
        }
    }
    return jni;
}

我知道JVM指针不为空,同样,代码在Windows上完美运行。如果由于某种原因无法在 Linux 上附加本机线程,我总是对替代方案持开放态度:我试图实现的目标基本上是回调到我的 Java 代码中。C++中发生了一个事件,例如对文件打开的请求,我需要能够在 Java 中处理它。

更新:我的JVM版本,包括javajavac,这是我用来编译和运行程序的版本。

openjdk version "1.8.0_191"
OpenJDK Runtime Environment (build 1.8.0_191-8u191-b12-2ubuntu0.18.10.1-b12)
OpenJDK 64-Bit Server VM (build 25.191-b12, mixed mode)
javac 1.8.0_191

可能你在 Linux 上的 JVM 不兼容 Java 8。没有理由要求JNI_VERSION_1_8除非您使用某些Java 8 JNI功能。通常,JNI_VERSION_1_6就足够了。

请参阅 JNI Linux 分段错误。当从Windows切换到Linux时,同样的FMODWrapper也是如此。

根本原因可能是包装器中使用的记录器。正如Lóránt Viktor Gerber在那里显示的那样,记录器是用对java/lang/System的本地引用初始化的。如果这个记录器以某种方式参与Utils::getJNI(),它将失败。

代码的另一个可疑部分是将临时名称传递给AttachCurrentThreadAsDaemon()。我会尝试将其设置为 nullptr 以排除任何干扰。

如果上述所有方法都不起作用,请检查 Linux 环境中是否仍然AttachCurrentThreadAsDaemon()(不是守护程序(仍然失败。