JNI launching a java application

Being a java newb, a lot of the JNI code confuses me.

I have a java application that I wish to run through a JNI wrapper.

What is the most simple C++ code that will enable me to do so.

Also most of the code posted for doing this uses various header files. Where can one find these header files, and also which compiler is needed for compiling the wrapper. I assume Gpp or similar - is this assumption correct?

[434 byte] By [bavardagea] at [2007-11-26 14:20:43]
# 1

> What is the most simple C++ code that will enable me to do so.

You have to use the JNI Invocation API.

For a little sample have a look here: [url http://java.sun.com/javase/6/docs/technotes/guides/jni/spec/invocation.html#wp15926]Invocation API Overview[/url]

Or here: [url http://www.rgagnon.com/javadetails/java-0354.html]Start a JVM from C[/url]

> Where can one find these header files

Under the {JDK_HOME}/include and {JDK_HOME}/include/{OS_SPECIFIC} folders

Eg. On a Windows machine it could be: c:\jdk1.6\include and c:\jdk1.6\include\win32

> which compiler is needed for compiling the wrapper. I assume Gpp or similar

It's called gcc and yes you should use it.

(On Windows you should use it by installing Cygwin *or* Mingw/Msys)

Regards

jfbrierea at 2007-7-8 2:12:12 > top of Java-index,Java HotSpot Virtual Machine,Specifications...
# 2

When using both of those examples I get numerous compiler errors - using the sun invocation api example;

#include <jni.h>/* where everything is defined */

...

JavaVM *jvm;/* denotes a Java VM */

JNIEnv *env;/* pointer to native method interface */

JavaVMInitArgs vm_args; /* JDK/JRE 6 VM initialization arguments */

JavaVMOption* options = new JavaVMOption[1];

options[0].optionString = "-Djava.class.path=/usr/lib/java";

vm_args.version = JNI_VERSION_1_6;

vm_args.nOptions = 1;

vm_args.options = options;

vm_args.ignoreUnrecognized = false;

/* load and initialize a Java VM, return a JNI interface

* pointer in env */

JNI_CreateJavaVM(&jvm, &env, &vm_args);

delete options;

/* invoke the Main.test method using the JNI */

jclass cls = env->FindClass("Main");

jmethodID mid = env->GetStaticMethodID(cls, "test", "(I)V");

env->CallStaticVoidMethod(cls, mid, 100);

/* We are done. */

jvm->DestroyJavaVM();

and I get the following errors:

Compiler: Default compiler

Building Makefile: "C:\Program Files\Dev-Cpp\Makefile.win"

Executing make...

make.exe -f "C:\Program Files\Dev-Cpp\Makefile.win" all

g++.exe -c ../../package/vocab.cpp -o ../../package/vocab.o -I"C:/Program Files/Dev-Cpp/include/c++" -I"C:/Program Files/Dev-Cpp/include/c++/mingw32" -I"C:/Program Files/Dev-Cpp/include/c++/backward" -I"C:/Program Files/Dev-Cpp/include" -I"C:/Program FIles/Java/jdk1.6.0/include/win32" -I"C:/Program FIles/Java/jdk1.6.0/include"

../../package/vocab.cpp:7: syntax error before `.' token

../../package/vocab.cpp:8: syntax error before `.' token

../../package/vocab.cpp:9: syntax error before `.' token

../../package/vocab.cpp:10: syntax error before `.' token

../../package/vocab.cpp:11: syntax error before `.' token

../../package/vocab.cpp:14: ISO C++ forbids declaration of `JNI_CreateJavaVM'

with no type

../../package/vocab.cpp:14: `int JNI_CreateJavaVM' redeclared as different kind

of symbol

C:/Program FIles/Java/jdk1.6.0/include/jni.h:1920: previous declaration of `

jint JNI_CreateJavaVM(JavaVM**, void**, void*)'

../../package/vocab.cpp:14: initializer list being treated as compound

expression

../../package/vocab.cpp:14: invalid conversion from `JavaVMInitArgs*' to `int'

../../package/vocab.cpp:15: parse error before `delete'

../../package/vocab.cpp:19: syntax error before `->' token

../../package/vocab.cpp:21: syntax error before `->' token

make.exe: *** [../../package/vocab.o] Error 1

Execution terminated

That is compiling using dev-C++ and I think the mingw compiler...

bavardagea at 2007-7-8 2:12:12 > top of Java-index,Java HotSpot Virtual Machine,Specifications...
# 3
I have made such tool but for MS Visual Studios 6.0 and 7.1 http://www.simtel.net/product.php[id]93174[SiteID]simtel.net http://www.simtel.net/product.php[id]94368[sekid]0[SiteID]simtel.net
vitallisa at 2007-7-8 2:12:12 > top of Java-index,Java HotSpot Virtual Machine,Specifications...
# 4
Add the following define to your compilation step:__int64="long long"On the g++ command line it should looks like:g++.exe -c -D__int64="long long" ...Regards
jfbrierea at 2007-7-8 2:12:12 > top of Java-index,Java HotSpot Virtual Machine,Specifications...
# 5

I tried the other example code to some success:

after following the steps etc I have a compiled program.

When run from the command line I can confirm it is loading the class (My program prints to System.out every second) however the program exits after only two seconds (as soon as the JFrame is displayed.)

Is there any way I can trace the source of this problem? - my knowledge of JNI is not sufficient to be able to build in error reporting to the program.

bavardagea at 2007-7-8 2:12:12 > top of Java-index,Java HotSpot Virtual Machine,Specifications...
# 6

Just to be clear, you are trying to execute Main.test(100) with Java class like:class Main {

static void test(int n) {

...

}

}

right?

After calling your Java method in C++ check for an exception to print at the console:

env->CallStaticVoidMethod(cls, mid, 100);

if (env->ExceptionCheck())

env->ExceptionDescribe();

Regards

jfbrierea at 2007-7-8 2:12:12 > top of Java-index,Java HotSpot Virtual Machine,Specifications...
# 7
Thanks.. will give it a try :D
bavardagea at 2007-7-8 2:12:12 > top of Java-index,Java HotSpot Virtual Machine,Specifications...
# 8

I am trying to launch my classes main method:

helloWorldClass = (*env)->FindClass(env, "be/bavardage/vocab/VocabGUI");

mainMethod = (*env)->GetStaticMethodID(env, helloWorldClass, "main", "([Ljava/lang/String;)V");

applicationArgs = (*env)->NewObjectArray(env, 1, (*env)->FindClass(env, "java/lang/String"), NULL);

applicationArg0 = (*env)->NewStringUTF(env, "From-C-program");

(*env)->SetObjectArrayElement(env, applicationArgs, 0, applicationArg0);

After adding the code that you suggested, after:

(*env)->CallStaticVoidMethod(env, helloWorldClass, mainMethod, applicationArgs);

I still get nothing printed. What stops the C++ program from finishing executing, thus terminating the virtual machine?

Should I put the exception checking in an infinite do.. while loop or similar?

Should I put the exception checking code in the main method?

bavardagea at 2007-7-8 2:12:12 > top of Java-index,Java HotSpot Virtual Machine,Specifications...
# 9

I seem to have it working - it appears there was no exception, but the program was merely exiting as soon as the JFrame launched. The while loop solved this, however meant that the cpu was bogged down with the joys of infinite while loops.

What is the generally accepted method of keeping the wrapper alive until the program has stopped executing?

bavardagea at 2007-7-8 2:12:12 > top of Java-index,Java HotSpot Virtual Machine,Specifications...
# 10

The java command normally runs until there are no non daemon threads left alive. If you are creating the JVM from scratch using JNI_CreateJavaVM then it's your responsibility to shut it down using DestroyJavaVM which is hanging off the JavaVM object handed back by JNI_CreateJavaVM. This will wait around until all non daemon threads have exited, just like the java command does.

tom

neverevera at 2007-7-8 2:12:12 > top of Java-index,Java HotSpot Virtual Machine,Specifications...