Version 1 (modified by trac, 15 years ago) |
---|
Java Support in ZOO Kernel
This is a sample program which dynamicaly loads JVM then load a Class to run one of its static methods :
//sample.c file #include <unistd.h> #include <jni.h> int main(int argc, char *argv[], char **envp) { JavaVMOption options[2]; JavaVMInitArgs vm_args; JavaVM *jvm; JNIEnv *env; long result; jmethodID mid; jfieldID fid; jobject jobj; jclass cls; int i, asize; options[0].optionString = "-Djava.class.path=."; options[1].optionString = "-Djava.compiler=NONE"; vm_args.version = JNI_VERSION_1_4; vm_args.options = options; vm_args.nOptions = 2; vm_args.ignoreUnrecognized = JNI_FALSE; result = JNI_CreateJavaVM( &jvm,(void **)&env, &vm_args); if(result == JNI_ERR ) { printf("Error invoking the JVM"); return 1; } else printf("JAVA VM Started\n"); cls = (*env)->FindClass(env,argv[1]); if( cls == NULL ) { printf("can't find class %s\n",argv[1]); return 1; }else{ printf("%s loaded\n",argv[1]); } (*env)->ExceptionClear(env); mid=(*env)->GetStaticMethodID(env,cls, argv[2], "([Ljava/lang/String;)I"); if(mid==0) printf("%s.%s static method not loaded \n", argv[1],argv[2]); else{ printf("%s.%s static method loaded \n",argv[1],argv[2] ); (*env)->CallStaticVoidMethod(env,cls, mid, "MID"); } (*jvm)->DestroyJavaVM(jvm); }
The sample program can be compiled this way (we will use $SDK_ROOT for the java sdk installation directory) :
gcc -I $SDK_ROOT/include/ -I $SDK_ROOT/include/linux/ -o sample sample.c -L $SDK_ROOT/jre/lib/i386/ -ljavaplugin_jni -L $SDK_ROOT/jre/lib/i386/server/ -ljvm -lpthread
You need now to use a sample Java Class, you can use the simple code bellow :
// HelloWorld.java file import java.util.*; public class HelloJava { public static int HelloWorldJava(String[] args) { System.out.println("Hello from JAVA WOrld !"); return 3; } }
You have now to compile your small java code using javac which should create a HelloWorld.class file in the current directory :
javac HelloWrold.java
To run this sample program you can simply use the following command :
LD_LIBRARY_PATH=".:$SDK_ROOT/jre/lib/i386/server/:$SDK_ROOT/jre/lib/i386/" ./sample HelloJava HelloWorldJava
Which should result in a similar result :
JAVA VM Started HelloJava loaded HelloJava.HelloWorldJava static method loaded Hello from JAVA WOrld !
This method need to load the jvm for every call.
The data structure selected was java.util.HashMap? to share data fom/to C to/from JAVA. Sample creation of this data structure in C :
jclass scReplyClass,scInfo_class; jmethodID scInfo_constructor; jobject scObject,scObject1; scReplyClass = (*env)->FindClass(env, "java/util/HashMap"); scInfo_class = (*env)->NewGlobalRef(env, scReplyClass); scInfo_constructor = (*env)->GetMethodID(env, scInfo_class, "<init>", "()V"); // no parameters if(scInfo_constructor==NULL) scInfo_constructor = (*env)->GetMethodID(env, scReplyClass, "<init>", "()V"); // no parameters if(scInfo_constructor!=NULL){ scObject = (*env)->NewObject(env, scInfo_class, scInfo_constructor); scObject1 = (*env)->NewObject(env, scInfo_class, scInfo_constructor); jmethodID put_mid = 0; put_mid = (*env)->GetMethodID(env,scReplyClass, "put", "(Ljava/lang/Object;Ljava/lang/Object;)" "Ljava/lang/Object;"); (*env)->CallObjectMethod(env,scObject1, put_mid, (*env)->NewStringUTF(env,"demoKey"), (*env)->NewStringUTF(env,"demoValue")); (*env)->CallObjectMethod(env,scObject1, put_mid, (*env)->NewStringUTF(env,"demoKey1"), (*env)->NewStringUTF(env,"demoValue1")); (*env)->CallObjectMethod(env,scObject1, put_mid, (*env)->NewStringUTF(env,"demoKey2"), (*env)->NewStringUTF(env,"demoValue2")); (*env)->CallObjectMethod(env,scObject1, put_mid, (*env)->NewStringUTF(env,"demoKey3"), (*env)->NewStringUTF(env,"demoValue3")); (*env)->CallObjectMethod(env,scObject1, put_mid, (*env)->NewStringUTF(env,"demoInput"), scObject1); } else printf("Unable to find java.util.HashMap constructor !\n");