ページ

2014年9月22日月曜日

JNIを使ってみる 2

CプログラムからJavaクラスの実行

CからJavaクラスを実行する為にはJavaVMを生成し実行してやらないといけないらしい

順序
  1. Java仮想マシンに渡すオプション値を生成
  2. Java仮想マシン生成
  3. 実行するクラスを検索後ロードする
  4. メソッドIDの取得
  5. メソッドに渡す引数があれば生成
  6. メソッド呼び出し
  7. Java仮想マシンの消滅

・呼び出されるJava側 InvocationApiTest.java
public class InvocationApiTest {
 public static void main(String[] args) {
  System.out.println(args[0]);
 }
}



・呼び出すC側 invocationApi.c
#include <jni.h>
int main() {

 JNIEnv *env;
 JavaVM *vm;
 JavaVMInitArgs vm_args;
 JavaVMOption options[1];
 jint res;
 jclass cls;
 jmethodID mid;
 jstring jstr;
 jclass stringClass;
 jobjectArray args;

 // 1. 仮想マシンに伝えるオプション値を生成
 options[0].optionString = "-Djava.class.path=.";
 vm_args.version = 0x00010002;
 vm_args.options = options;
 vm_args.nOptions = 1;
 vm_args.ignoreUnrecognized = JNI_TRUE;

 // 2. Java仮想マシン生成
 res = JNI_CreateJavaVM(&vm, (void **)&env, &vm_args);

 // 3. 実行するクラスを検索後ロードする
 cls = (*env)->FindClass(env, "InvocationApiTest");

 // 4. main()メソッドのメソッドID取得
 mid = (*env)->GetStaticMethodID(env, cls, "main", "([Ljava/lang/String;)V");

 // 5. Javaのmainクラスメソッド引数生成
 jstr = (*env)->NewStringUTF(env, "Hello Invocation API!!");
 stringClass = (*env)->FindClass(env, "java/lang/String");
 args = (*env)->NewObjectArray(env, 1, stringClass, jstr);

 // 6. main()メソッド呼び出し
 (*env)->CallStaticVoidMethod(env, cls, mid, args);

 // 7. Java仮想マシン消滅
 (*vm)->DestroyJavaVM(vm);
}



Javaファイルをclassファイルへコンパイル
  > javac InvocationApiTest.java

C側のコンパイル
Visual Studio Tool > Cross Tools コマンドプロンプトを起動
 > cl -I"<JDK_HOME>/include" -I"<JDK_HOME>/include/win32" invocationApi.c
        -link "<JDK_HOME>/lib/jvm.lib"

invocationApi.exeができあがるはず。
実行しようとするとエラーがっ ><












どうやら環境変数に"<JDK_HOME>/jre/bin/server"を追加しないといけないらしい。
設定していざ実行すると・・


















無事実行できました^^

0 件のコメント:

コメントを投稿