Next: , Previous: Synchronization, Up: About CNI


11.16 Invocation

CNI permits C++ applications to make calls into Java classes, in addition to allowing Java code to call into C++. Several functions, known as the invocation API, are provided to support this.

— Function: jint JvCreateJavaVM (JvVMInitArgs* vm_args)

Initializes the Java runtime. This function performs essential initialization of the threads interface, garbage collector, exception handling and other key aspects of the runtime. It must be called once by an application with a non-Java main() function, before any other Java or CNI calls are made. It is safe, but not recommended, to call JvCreateJavaVM() more than once provided it is only called from a single thread. The vmargs parameter can be used to specify initialization parameters for the Java runtime. It may be NULL.

JvVMInitArgs represents a list of virtual machine initialization arguments. JvCreateJavaVM() ignores the version field.

          typedef struct JvVMOption
          {
            // a VM initialization option
            char* optionString;
            // extra information associated with this option
            void* extraInfo;
          } JvVMOption;
          
          typedef struct JvVMInitArgs
          {
            // for compatibility with JavaVMInitArgs
            jint version;
          
            // number of VM initialization options
            jint nOptions;
          
            // an array of VM initialization options
            JvVMOption* options;
          
            // true if the option parser should ignore unrecognized options
            jboolean ignoreUnrecognized;
          } JvVMInitArgs;
     

JvCreateJavaVM() returns 0 upon success, or -1 if the runtime is already initialized.

Note: In GCJ 3.1, the vm_args parameter is ignored. It is recognized and used as of release 4.0.

— Function: java::lang::Thread* JvAttachCurrentThread (jstring name, java::lang::ThreadGroup* group)

Registers an existing thread with the Java runtime. This must be called once from each thread, before that thread makes any other Java or CNI calls. It must be called after JvCreateJavaVM. name specifies a name for the thread. It may be NULL, in which case a name will be generated. group is the ThreadGroup in which this thread will be a member. If it is NULL, the thread will be a member of the main thread group. The return value is the Java Thread object that represents the thread. It is safe to call JvAttachCurrentThread() more than once from the same thread. If the thread is already attached, the call is ignored and the current thread object is returned.

— Function: jint JvDetachCurrentThread ()

Unregisters a thread from the Java runtime. This should be called by threads that were attached using JvAttachCurrentThread(), after they have finished making calls to Java code. This ensures that any resources associated with the thread become eligible for garbage collection. This function returns 0 upon success, or -1 if the current thread is not attached.

11.16.1 Handling uncaught exceptions

If an exception is thrown from Java code called using the invocation API, and no handler for the exception can be found, the runtime will abort the application. In order to make the application more robust, it is recommended that code which uses the invocation API be wrapped by a top-level try/catch block that catches all Java exceptions.

11.16.2 Example

The following code demonstrates the use of the invocation API. In this example, the C++ application initializes the Java runtime and attaches itself. The java.lang.System class is initialized in order to access its out field, and a Java string is printed. Finally, the thread is detached from the runtime once it has finished making Java calls. Everything is wrapped with a try/catch block to provide a default handler for any uncaught exceptions.

The example can be compiled with c++ -c test.cc; gcj test.o.

     // test.cc
     #include <gcj/cni.h>
     #include <java/lang/System.h>
     #include <java/io/PrintStream.h>
     #include <java/lang/Throwable.h>
     
     int main(int argc, char *argv[])
     {
       using namespace java::lang;
     
       try
       {
         JvCreateJavaVM(NULL);
         JvAttachCurrentThread(NULL, NULL);
     
         String *message = JvNewStringLatin1("Hello from C++");
         JvInitClass(&System::class$);
         System::out->println(message);
     
         JvDetachCurrentThread();
       }
       catch (Throwable *t)
       {
         System::err->println(JvNewStringLatin1("Unhandled Java exception:"));
         t->printStackTrace();
       }
     }