LinuxでJNIを使ってCからJavaを実行してみる(起動だけ)
先日、JavaからCを書きましたが、今度はCからJavaを実行してみます。メソッド呼び出しとかはまだちょっと置いておいて、まずはJava VMの生成、破棄から。
ソースコード(JVMクラス)
Cといいつつ、C++でクラスっぽくして書いてみました。諸々の判定なんかは簡略化してますのであしからず。
#include <jni.h> #include <iostream> using namespace std; class JVM { JavaVM *_vm; JNIEnv *_env; public: int create(); int destroy(); } jvm; int JVM::create() { jint ret; if (_vm != NULL) return JNI_OK; JavaVMInitArgs initArgs; initArgs.version = JNI_VERSION_1_6; ret = JNI_GetDefaultJavaVMInitArgs(&initArgs); if (ret != JNI_OK) { cerr << "[ERROR] JNI_GetDefaultJavaVMInitArgs : " << ret << endl; return ret; } JavaVMOption options[3]; options[0].optionString = "-Djava.compile=NONE"; options[1].optionString = "-Djava.class.path=."; options[2].optionString = "-verbose:jni"; initArgs.nOptions = 2; initArgs.options = options; ret = JNI_CreateJavaVM(&_vm, (void**)&_env, &initArgs); if (ret != JNI_OK) { cerr << "[ERROR] JNI_CreateJavaVM : " << ret << endl; return ret; } return ret; } int JVM::destroy() { jint ret = JNI_OK; if (_vm == NULL) return JNI_OK; ret = _vm->DestroyJavaVM(); if (ret != JNI_OK) { cerr << "[ERROR] DestroyJavaVM : " << ret << endl; } else { _vm = NULL; _env = NULL; } return ret; }
Java VMをクラスにしたときの名前がかなり微妙です。。。JavaVMという構造体がすでに存在するので仕方なく。で、この微妙なJVMクラスをこれを単純にグローバルにしてます。
ソースコード(main)
起動、生成は以下の通り。
int main(int argc, char *argv[]) { int ret; ret = jvm.create(); cout << "JavaVM create : " << ret << endl; ret = jvm.destroy(); cout << "JavaVM destroy : " << ret << endl; return 0; }
まぁこれだけじゃ何もできませんね。
コンパイル、実行
コンパイル、実行は以下の通り、ソースファイル名はfirststerp.c++です。(JAVA_HOMEは適切に設定しましょう。)
$> g++ -I$JAVA_HOME/include -I$JAVA_HOME/include/linux -L$JAVA_HOME/jre/lib/i386/client -ljvm -o firststep firststep.c++ $> export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$JAVA_HOME/jre/lib/i386/client $> ./firststep JavaVM create : 0 JavaVM destroy : 0 $>
生成、破棄が無事にできました。
でもなぜかエラー(原因不明)
ところで、生成、破棄をしたあとさらに生成を行うと、なぜかエラーになります。JNI_ERR(unknown error)が返されるのでよく分かりません。。。
こんな感じ。
int main(int argc, char *argv[]) { int ret; ret = jvm.create(); cout << "JavaVM create : " << ret << endl; ret = jvm.destroy(); cout << "JavaVM destroy : " << ret << endl; ret = jvm.create(); cout << "JavaVM create : " << ret << endl; return 0; }
実行してみると。
JavaVM create : 0 JavaVM destroy : 0 [ERROR] JNI_CreateJavaVM : -1 JavaVM create : -1
んー、よく分からん。一度DestroyJavaVMをしたら、2度とCreateできないということなのだろうかなぁ。必ずプロセスの中で生成、破棄は1度ずつしかしちゃダメよってことだと勝手に理解。