前回の「air:ANEでちょっと試してみたいことはJavaの起動」のところで、
CからJavaを起動する方法を紹介しました。

しかし、WindowsやLinuxなどを使っていると、そもそもJavaってどこにあることにすればいいの?
ということが起きるでしょう。
つまり、jvm.dllやlibjvm.soをリンクしないという方法をとる必要があります。
従って、ダイナミックローディングとなるわけです。

今回のターゲットはLinuxとWindowsです。
ということで、APRを使ってダイナミックローディングを実現します。
(aprを使えば、このあたりでOSの違いを意識せずにコーディングできます。)

Macでもほぼ同じコードでできるかと思っていましたが、できませんでした。
(ただ、理由はわかりません。)

#include <jni .h>
#include <stdio .h>
#include <stdlib .h>

#include <apr_general .h>
#include <apr_dso .h>
#include <apr_file_io .h>

apr_file_t *apr_stdout;
apr_file_t *apr_stderr;

int my_main(){

	apr_initialize();

	apr_status_t rv;
	apr_pool_t *pool;

	rv = apr_pool_create(&pool,NULL);
	if ( APR_SUCCESS != rv ){
		return __LINE__;
	}

	rv = apr_file_open_stderr(&apr_stderr,pool);
	if ( APR_SUCCESS != rv ){
		return __LINE__;
	}

	apr_dso_handle_t *dso_handle;
	apr_dso_handle_sym_t *dso_sym;

	rv = apr_dso_load(&dso_handle,"libjvm.so",pool);
	if ( APR_SUCCESS != rv ){
		return __LINE__;
	}

	JNIEnv *env;
	JavaVM *jvm;
	jclass clazz;
	jmethodID methodId;

	JavaVMOption options[3];
	options[0].optionString = "-Xmx128m";
	options[1].optionString = "-verbose:gc";
	options[2].optionString = "-Djava.class.path=classes";
	JavaVMInitArgs vm_args;
	vm_args.version = JNI_VERSION_1_6;
	vm_args.options = options;
	vm_args.nOptions = 3;

	typedef int (*dso_JNI_CreateJavaVM_t)(JavaVM **jvm, void **jni_env, void *jvm_args);
	dso_JNI_CreateJavaVM_t dso_JNI_CreateJavaVM;

	rv = apr_dso_sym((apr_dso_handle_sym_t*)&dso_JNI_CreateJavaVM,dso_handle,"JNI_CreateJavaVM");
	if ( APR_SUCCESS != rv ) {
		return __LINE__;
	}

	int ret = dso_JNI_CreateJavaVM(&jvm,(void **)&env, &vm_args);
	if ( ret < 0 ){
		return __LINE__;
	}

	clazz = (*env)->FindClass(env, "Hello");
	if( clazz == 0){
		return __LINE__;
	}
	methodId = (*env)->GetStaticMethodID(env,clazz,"main","([Ljava/lang/String;)V");
	if ( methodId == 0){
		return __LINE__;
	}
	(*env)->CallStaticVoidMethod(env,clazz,methodId,NULL	);

	(*jvm)->DestroyJavaVM(jvm);

	apr_terminate();
	return APR_SUCCESS;
}

int main(int argc, char **argv){
	int ret = my_main();
	if ( APR_SUCCESS != ret ){
		if(apr_stderr != NULL){
			apr_file_printf(apr_stderr,"failed ; [%d]\n",ret);
		}
	}
}

とこんな感じです。
コンパイルとリンクの方法はこれまでのブログを参考にしていけばできると思います。
ちなみに、Windowsの場合には

rv = apr_dso_load(&dso_handle,"libjvm.so",pool);

の部分をjvm.dllへの完全パスを指定すれば間違いないと思います。

これで、javaがインストールされてれば、そこを指定して起動ができるようになったという訳です。
代わりに、aprの依存ができてしまいましたが・・・

関係ありませんが、このソースを記述していてC言語ってやっぱり、
メモリ操作なんだなーとしみじみと思ってしまいました。

rv = apr_dso_sym((apr_dso_handle_sym_t*)&dso_JNI_CreateJavaVM,dso_handle,"JNI_CreateJavaVM");

って、要はsoファイルが展開されたメモリ上のJNI_CreateJavaVMの関数のアドレス位置を取得しているってことですよね。
でもって、次にそれを実行する。

Javaをやっていると、「正しくコーディングする」がしっくりきますが、
Cをやっていると、「正しく動くようにコーディングする」という感じになります。
(’関数の実行や、変数の操作レベルの話です。)

お仕事のご依頼・相談を承ります
この記事に関連するお仕事のご依頼やご相談をお待ちしております。 詳しくは、こちら

Leave a Reply

お仕事のご依頼・相談
この記事に関連するお仕事のご依頼やご相談をお待ちしております。 詳しくは、こちら
ソフトウェア&ライブラリ




ライブラリ
airxmail(en)
AIR版メール送受信ライブラリ
airxzip
AIR版ZIP圧縮・解凍ライブラリ
執筆書籍
本、雑誌等

WEB記事:CodeZine
執筆記事はこちら
カレンダー
2012年3月
« 2月   4月 »
 1234
567891011
12131415161718
19202122232425
262728293031  

カスタム検索
RSS
Add to Google < !–adsense–>
アーカイブ
カテゴリ
にほんブログ村 IT技術ブログへ