1

I'm writing a JNI wrapper around a native C++ library, but I'm having trouble attaching native threads to the JVM on Linux. Everything works fine on Windows, but when I call AttachNativeThread() on an Ubuntu machine, it always returns -1.

This is the way I'm getting JNIEnv pointers:

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;
}

I know that the JVM pointer is not null, and again, the code works flawlessly on Windows. If it's not possible to attach native threads on Linux for some reason, I'm always open to alternatives: the thing I'm trying to achieve are basically callbacks into my Java code. An event happens in C++, for example a request for File open, and I need to be able to handle that in Java.

Update: My JVM versions, both java and javac, this is what I used to compile and run the program.

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

2 Answers2

0

Possibly your JVM on Linux is not Java 8 compatible. There is no reason to ask for JNI_VERSION_1_8 unless you use some Java 8 JNI features. Usually, JNI_VERSION_1_6 will suffice.

Alex Cohn
  • 56,089
  • 9
  • 113
  • 307
0

See JNI Linux segmentation fault. This is the same problem with the same FMODWrapper when switching from Windows to Linux.

The root cause could be the logger that is used in your wrapper. As Lóránt Viktor Gerber shows there, the logger is initialized with a local reference to java/lang/System. If this logger is somehow involved in Utils::getJNI(), it will fail.

Another suspicious part of your code is passing a temporary name to AttachCurrentThreadAsDaemon(). I would try to set it to nullptr to exclude any interference.

If all the above does not work, check if AttachCurrentThreadAsDaemon() (not as a daemon) still fails in your Linux environment.

Alex Cohn
  • 56,089
  • 9
  • 113
  • 307