Das folgende Beispiel demonstriert die Verwendung des Java-Invocation-APIs (Teil des JNI) für den Aufruf von Java-Programmen aus C heraus. Das gewählte Beispiel ist absichtlich einfach gehalten.
Ein Java-Echo-Programm gebe alle seine Argumente auf die Standard-Ausgabe aus. Aus einem C-Programm wird dieses Java-Programm dann aufgerufen.
Implementierung des Java-Codes
In der Datei Echo.java sei die folgende Klasse definiert:
class Echo { public static void main(String[] args) { for (int i = 0; i < args.length; i++) { if (i > 0) System.out.print(" "); System.out.print(args[i]); } System.out.println(""); } }
Compilieren des Java-Codes
Die oben definierte Java-Klasse kann jetzt einfach mit dem Kommando
javac Echo.java
compiliert werden. Durch Aufruf von
java Echo Das ist ein Versuch
können Sie sich vom Funktionieren des Programms überzeugen.
Implementieren des C-Codes
Das folgende C-Programm soll obiges Java-Programm aufrufen und ihm seine Aufrufargumente dabei übergeben. Besonders zu beachten ist wiederum, dass alle an en übergebe-nen Strings ASCII-codiert sein müssen. Dieses Beispiel wird daher vollständig im ASCII-Modus implementiert und produziert.
Die Datei Echo.c sei nun folgendermaßen implementiert:
#include <jni.h> int main(int argc, char *argv[]) { JavaVMInitArgs vm_args; JavaVMOption options[1]; JavaVM *jvm; JNIEnv *env; jint res; jclass cls; jmethodID mid; jobjectArray args; int i; /* ** Prepare VM Options */ options[0].optionString = "-Djava.class.path=."; /* ** Prepare VM configuration */ vm_args.version = JNI_VERSION_1_4; vm_args.nOptions = 1; vm_args.options = options; vm_args.ignoreUnrecognized = JNI_FALSE; /* ** Create the Java VM */ res = JNI_CreateJavaVM(&jvm,(void **)&env,&vm_args); if (res < 0) { fprintf(stderr,"Can't create Java VM\n"); exit(1); } /* ** Get class Echo */ cls = (*env)->FindClass(env,"Echo"); if (cls == NULL) { fprintf(stderr,"Can't find Echo class\n"); exit(1); } /* ** Get main method */ mid = (*env)->GetStaticMethodID(env,cls,"main", "([Ljava/lang/String;)V"); if (mid == 0) { fprintf(stderr,"Can't find main in Echo\n"); exit(1); } /* ** Allocate argument array */ args = (*env)->NewObjectArray(env,argc-1, (*env)->FindClass(env,"java/lang/String"),NULL); if (args == 0) { fprintf(stderr,"Out of memory\n"); exit(1); } /* ** Prepare arguments */ for (i=1; i<argc; i++) { jstring jstr; jstr = (*env)->NewStringUTF(env,argv[i]); if (jstr == NULL) { fprintf(stderr,"Out of memory\n"); exit(1); } (*env)->SetObjectArrayElement(env,args,i-1,jstr); } /* ** Call Java method */ (*env)->CallStaticVoidMethod(env,cls,mid,args); /* ** Destroy Java VM */ (*jvm)->DestroyJavaVM(jvm); return 0; }
Das Programm arbeitet in dieser Form nur mit einer Standard-Installation von JENV zusammen. Für den Ablauf mit einer Privat-Installation müssen Sie die Umgebungsvariable JAVA_HOME entsprechend setzen (siehe Kapitel „Umgebungsvariablen").
Übersetzen der C-Source
Die im vorigen Abschnitt implementierte C-Source muss nun mit den richtigen CompilerOptionen übersetzt werden. Für Echo.c muss zusätzlich zu den Standard-Optionen, die weiter oben beschrieben wurden, noch der ASCII-Modus berücksichtigt werden:
cc -c -I<Installations-Pfad>/include \ -Kllm_keep,llm_case_lower \ -Kworkspace_stack,c_names_unlimited \ -Kliteral_encoding_ascii \ -Kno_integer_overflow Echo.c
Als Ergebnis steht eine Objekt-Datei zur Verfügung.
Binden und Ausführen der Anwendung
Beim Binden der Anwendung muss berücksichtigt werden, dass der Laufzeit-Adapter von Java mit eingebunden wird und nicht die „normalen“ Laufzeitsysteme.
Mit den folgenden Kommandos kann die Anwendung gebunden werden:
export BLSLIB00='$.SYSLNK.JENV.110.GREEN-JAVA' cc -Kno_link_stdlibs -B llm4 -o Echo \ Echo.o -l BLSLIB
Das Programm kann dann wie jedes andere POSIX-Programm aufgerufen werden. Es benötigt zum Ablauf aber ein unter dem Standard-Installationspfad installiertes JENV. Für die Verwendung eines anderswo installierten JENV muss die Umgebungsvariable JAVA_HOME entsprechend gesetzt werden (siehe Kapitel „Umgebungsvariablen").
Der Aufruf mittels
Echo Das ist ein Java-Echo
führt zu der erwarteten Ausgabe:
Das ist ein Java-Echo
Das Programm wird mit der in Abschnitt „Option zur Auswahl des HotSpot TM VM-Typs" im Abschnitt "java" beschriebenen Default-VM ausgeführt. Durch vorheriges Setzen der Umgebungsvariable JENV_VMTYPE kann der VM-Typ explizit bestimmt werden. Also z.B.:
export JENV_VMTYPE=client
Dies bewirkt, dass die HotSpotTM Client-VM zur Ausführung verwendet wird.