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.
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 callJvCreateJavaVM()
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 beNULL
.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()
returns0
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.
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 beNULL
, in which case a name will be generated. group is the ThreadGroup in which this thread will be a member. If it isNULL
, the thread will be a member of the main thread group. The return value is the JavaThread
object that represents the thread. It is safe to callJvAttachCurrentThread()
more than once from the same thread. If the thread is already attached, the call is ignored and the current thread object is returned.
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 returns0
upon success, or-1
if the current thread is not attached.
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.
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(); } }