Search code examples
javac++java-native-interface

How to prevent my JNI C code from exiting while the JVM it launched is still running a Java thread?


I'm writing a C++ application that will rely on another embedded Java application. The barebones of my C++ application is below. My question is how do I prevent it from exiting while the JVM is running my thread above?

#include <jni.h>

int main()
{
       Using namespace std;
       JavaVM *jvm;                      // Pointer to the JVM (Java Virtual Machine)
       JNIEnv *env;                      // Pointer to native interface
           //================== prepare loading of Java VM ============================
       JavaVMInitArgs vm_args;                        // Initialization arguments
       JavaVMOption* options = new JavaVMOption[1];   // JVM invocation options
       options[0].optionString = "-Djava.class.path=.";   // where to find java .class
       vm_args.version = JNI_VERSION_1_6;             // minimum Java version
       vm_args.nOptions = 1;                          // number of options
       vm_args.options = options;
       vm_args.ignoreUnrecognized = false;     // invalid options make the JVM init fail
           //=============== load and initialize Java VM and JNI interface =============
       jint rc = JNI_CreateJavaVM(&jvm, (void**)&env, &vm_args);  // YES !!
       delete options;    // we then no longer need the initialisation options. 
       if (rc != JNI_OK) {
              // TO DO: error processing... 
             cin.get();
             exit(EXIT_FAILURE);
       }
          //=============== Display JVM version =======================================
       cout << "JVM load succeeded!\n";

        // HERE I'LL CALL A STATIC METHOD ON A JAVA CLASS THAT WILL START A JAVA THREAD
        // What do I do here to keep my C application running while the JVM has my thread running?

       jvm->DestroyJavaVM();
}

Source: https://www.codeproject.com/Articles/993067/Calling-Java-from-Cplusplus-with-JNI


Solution

  • Assuming you can get hold of a reference to an instance of CallbackFromJava, you can just call thread.join() on it:

    jobject cbfj = ...;
    jclass cls_cbfj = env->GetObjectclass(cbfj);
    jfieldID fid_cbfj_thread = env->GetFieldID(cls_cbfj, "thread", "Ljava/lang/Thread;");
    jobject thread = env->GetObjectField(cbfj, fid_cbfj_thread);
    
    jclass cls_thread = env->GetObjectClass(thread);
    jmethodID mid_thread_join = env->GetMethodID(cls_thread, "join", "()V");
    env->CallVoidMethod(thread, mid_thread_join);