20
そんなに難しくない C/C++からJVMの起動 JJUGナイトセミナー2012-08-29 ライトニングトーク 高橋

Jjug night seminar201208_lt_cxxからjvm起動

  • Upload
    torutk

  • View
    851

  • Download
    0

Embed Size (px)

Citation preview

Page 1: Jjug night seminar201208_lt_cxxからjvm起動

そんなに難しくないC/C++からJVMの起動

JJUGナイトセミナー2012-08-29

ライトニングトーク

高橋 徹

Page 2: Jjug night seminar201208_lt_cxxからjvm起動

発表者について@boochnich

http://d.hatena.ne.jp/torutk/

• 仕事では、C/C++/Javaまんべんなく– 非Web系分散処理(CORBA、マルチキャスト・・・)

– GUI(Swing, X/Motif,GTK+・・・)

– GIS(地図)

• Java読書会BOF現代表– 1998年~毎月1回開催、通算161回、24冊

http://www.javareading.com/bof/

Page 3: Jjug night seminar201208_lt_cxxからjvm起動

JVMを起動するC++コード(骨子)#include <jni.h>

int main()

{

JavaVMOption options[2];

options[0].optionString = "-Xmx64m";

options[1].optionString = "-Djava.class.path=.";

JavaVMInitArgs vm_args;

vm_args.version = JNI_VERSION_1_6;

vm_args.options = options;

vm_args.nOptions = 2;

JNIEnv* env;

JavaVM* jvm;

int res = JNI_CreateJavaVM(&jvm, (void**)&env, &vm_args);

jclass clazz = env->FindClass("Hello");

jmethodID mid = env->GetStaticMethodID(clazz, "main", "([Ljava/lang/String;)V");

env->CallStaticVoidMethod(clazz, mid, NULL);

jvm->DestroyJavaVM();

}

説明用につき、

エラー処理、動作確認ログなどは省略しています。

Page 4: Jjug night seminar201208_lt_cxxからjvm起動

#include <jni.h>

int main()

{

JavaVMOption options[2];

options[0].optionString = "-Xmx64m";

options[1].optionString = "-Djava.class.path=.";

JavaVMInitArgs vm_args;

vm_args.version = JNI_VERSION_1_6;

vm_args.options = options;

vm_args.nOptions = 2;

JNIEnv* env;

JavaVM* jvm;

int res = JNI_CreateJavaVM(&jvm, (void**)&env, &vm_args);

jclass clazz = env->FindClass("Hello");

jmethodID mid = env->GetStaticMethodID(clazz, "main", "([Ljava/lang/String;)V");

env->CallStaticVoidMethod(clazz, mid, NULL);

jvm->DestroyJavaVM();

}

JVMを起動するC++コード(骨子)

Page 5: Jjug night seminar201208_lt_cxxからjvm起動

#include <jni.h>

int main()

{

JavaVMOption options[2];

options[0].optionString = "-Xmx64m";

options[1].optionString = "-Djava.class.path=.";

JavaVMInitArgs vm_args;

vm_args.version = JNI_VERSION_1_6;

vm_args.options = options;

vm_args.nOptions = 2;

JNIEnv* env;

JavaVM* jvm;

int res = JNI_CreateJavaVM(&jvm, (void**)&env, &vm_args);

jclass clazz = env->FindClass("Hello");

jmethodID mid = env->GetStaticMethodID(clazz, "main", "([Ljava/lang/String;)V");

env->CallStaticVoidMethod(clazz, mid, NULL);

JavaVMに指定するオプションを列挙

起動したJavaVMが使用するクラスパスは、システムプロパティ java.class.pathで定義

JVMを起動するC++コード(骨子)

Page 6: Jjug night seminar201208_lt_cxxからjvm起動

#include <jni.h>

int main()

{

JavaVMOption options[2];

options[0].optionString = "-Xmx64m";

options[1].optionString = "-Djava.class.path=.";

JavaVMInitArgs vm_args;

vm_args.version = JNI_VERSION_1_6;

vm_args.options = options;

vm_args.nOptions = 2;

JNIEnv* env;

JavaVM* jvm;

int res = JNI_CreateJavaVM(&jvm, (void**)&env, &vm_args);

jclass clazz = env->FindClass("Hello");

jmethodID mid = env->GetStaticMethodID(clazz, "main", "([Ljava/lang/String;)V");

env->CallStaticVoidMethod(clazz, mid, NULL);

JavaVMを起動するAPIに渡す設定

JNIのバージョン、JavaVMオプションを指定する

JVMを起動するC++コード(骨子)

Page 7: Jjug night seminar201208_lt_cxxからjvm起動

#include <jni.h>

int main()

{

JavaVMOption options[2];

options[0].optionString = "-Xmx64m";

options[1].optionString = "-Djava.class.path=.";

JavaVMInitArgs vm_args;

vm_args.version = JNI_VERSION_1_6;

vm_args.options = options;

vm_args.nOptions = 2;

JNIEnv* env;

JavaVM* jvm;

int res = JNI_CreateJavaVM(&jvm, (void**)&env, &vm_args);

jclass clazz = env->FindClass("Hello");

jmethodID mid = env->GetStaticMethodID(clazz, "main", "([Ljava/lang/String;)V");

env->CallStaticVoidMethod(clazz, mid, NULL);

<jni.h>に定義されている定数(JDK 7u6)#define JNI_VERSION_1_1 0x00010001#define JNI_VERSION_1_2 0x00010002#define JNI_VERSION_1_4 0x00010004#define JNI_VERSION_1_6 0x00010006

JVMを起動するC++コード(骨子)

Page 8: Jjug night seminar201208_lt_cxxからjvm起動

#include <jni.h>

int main()

{

JavaVMOption options[2];options[0].optionString = "-Xmx64m";

options[1].optionString = "-Djava.class.path=.";

JavaVMInitArgs vm_args;

vm_args.version = JNI_VERSION_1_6;

vm_args.options = options;

vm_args.nOptions = 2;

JNIEnv* env;

JavaVM* jvm;

int res = JNI_CreateJavaVM(&jvm, (void**)&env, &vm_args);

jclass clazz = env->FindClass("Hello");

jmethodID mid = env->GetStaticMethodID(clazz, "main", "([Ljava/lang/String;)V");

JVMを起動するC++コード(骨子)

Page 9: Jjug night seminar201208_lt_cxxからjvm起動

#include <jni.h>

int main()

{

JavaVMOption options[2];options[0].optionString = "-Xmx64m";

options[1].optionString = "-Djava.class.path=.";

JavaVMInitArgs vm_args;

vm_args.version = JNI_VERSION_1_6;

vm_args.options = options;

vm_args.nOptions = 2;

JNIEnv* env;

JavaVM* jvm;

int res = JNI_CreateJavaVM(&jvm, (void**)&env, &vm_args);

jclass clazz = env->FindClass("Hello");

jmethodID mid = env->GetStaticMethodID(clazz, "main", "([Ljava/lang/String;)V");

JVMを起動するC++コード(骨子)

Page 10: Jjug night seminar201208_lt_cxxからjvm起動

JavaVMInitArgs vm_args;

vm_args.version = JNI_VERSION_1_6;

vm_args.options = options;

vm_args.nOptions = 2;

JNIEnv* env;

JavaVM* jvm;

JNI_CreateJavaVM(&jvm, (void**)&env, &vm_args);jclass clazz = env->FindClass("Hello");

jmethodID mid = env->GetStaticMethodID(clazz, "main", "([Ljava/lang/String;)V");

env->CallStaticVoidMethod(clazz, mid, NULL);

jvm->DestroyJavaVM();

}

JavaVMを起動します

JVMを起動するC++コード(骨子)

Page 11: Jjug night seminar201208_lt_cxxからjvm起動

#include <jni.h>

int main()

{

JavaVMOption options[2];

options[0].optionString = "-Xmx64m";

options[1].optionString = "-Djava.class.path=.";

JavaVMInitArgs vm_args;

vm_args.version = JNI_VERSION_1_6;

vm_args.options = options;

vm_args.nOptions = 2;

JNIEnv* env;

JavaVM* jvm;

int res = JNI_CreateJavaVM(&jvm, (void**)&env, &vm_args);

jclass clazz = env->FindClass("Hello");jmethodID mid = env->GetStaticMethodID(clazz, "main", "([Ljava/lang/String;)V");

env->CallStaticVoidMethod(clazz, mid, NULL);

jvm->DestroyJavaVM();

}

起動したJavaVMにクラスをロードします。

クラスはFQCNで記述

JVMを起動するC++コード(骨子)

Page 12: Jjug night seminar201208_lt_cxxからjvm起動

JNIEnv* env;

JavaVM* jvm;

int res = JNI_CreateJavaVM(&jvm, (void**)&env, &vm_args);

jclass clazz = env->FindClass("Hello");

jmethodID mid = env->GetStaticMethodID(

clazz, "main", "([Ljava/lang/String;)V“

);env->CallStaticVoidMethod(clazz, mid, NULL);

jvm->DestroyJavaVM();

}

クラスのメソッドIDを取得します。

メソッド名メソッドシグニチャ(引数の型・戻り値型)

JVMを起動するC++コード(骨子)

Page 13: Jjug night seminar201208_lt_cxxからjvm起動

JNIEnv* env;

JavaVM* jvm;

int res = JNI_CreateJavaVM(&jvm, (void**)&env, &vm_args);

jclass clazz = env->FindClass("Hello");

jmethodID mid = env->GetStaticMethodID(

clazz, "main", "([Ljava/lang/String;)V“

);env->CallStaticVoidMethod(clazz, mid, NULL);

jvm->DestroyJavaVM();

}

シグニチャの調べ方

C:\work> javap -s Hello

Compiled from "Hello.java"public class Hello {public Hello();Signature: ()V

public static void main(java.lang.String[]);Signature: ([Ljava/lang/String;)V

}

JVMを起動するC++コード(骨子)

Page 14: Jjug night seminar201208_lt_cxxからjvm起動

JNIEnv* env;

JavaVM* jvm;

int res = JNI_CreateJavaVM(&jvm, (void**)&env, &vm_args);

jclass clazz = env->FindClass("Hello");

jmethodID mid = env->GetStaticMethodID(clazz, "main", "([Ljava/lang/String;)V");

env->CallStaticVoidMethod(clazz, mid, NULL);

jvm->DestroyJavaVM();

}

メソッドを実行します

JVMを起動するC++コード(骨子)

Page 15: Jjug night seminar201208_lt_cxxからjvm起動

JNIEnv* env;

JavaVM* jvm;

int res = JNI_CreateJavaVM(&jvm, (void**)&env, &vm_args);

jclass clazz = env->FindClass("Hello");

jmethodID mid = env->GetStaticMethodID(clazz, "main", "([Ljava/lang/String;)V");

env->CallStaticVoidMethod(clazz, mid, NULL);

jvm->DestroyJavaVM();}

JavaVMを破棄します

JVMを起動するC++コード(骨子)

Page 16: Jjug night seminar201208_lt_cxxからjvm起動

コンパイル・リンク

• Windows (Visual C++)の場合

cl /I"C:\Program Files (x86)\java\jdk1.7.0\include“

/I"C:\Program Files (x86)\java\jdk1.7.0\include\win32"

/EHsc

launch.cpp

/link

/LIBPATH:"C:\Program Files (x86)\Java\jdk1.7.0\lib“

jvm.lib

Page 17: Jjug night seminar201208_lt_cxxからjvm起動

実行

• Windows (Visual C++)の場合

C:\work> PATH=%PATH%;”C:\Program Files (x86)\java\

jdk1.7.0\jre\bin\client”

C:\work> launch

Hello, World!

C:\work>

Page 18: Jjug night seminar201208_lt_cxxからjvm起動

補足

• jvm.dllを明示的リンクせず暗黙的リンクすると柔軟性が増す

– LoadLibraryでjvm.dllを読み込む

– 複数バージョンのJavaVMを使い分ける等

• 非ASCII(日本語)文字列を渡す場合注意

– C/C++側で文字コードを扱うのは悲惨

– C++ 11で光明あり(u8”こんにちは”)

Page 19: Jjug night seminar201208_lt_cxxからjvm起動

情報源

• 公式ドキュメント(日本語訳版)– http://docs.oracle.com/javase/jp/6/technotes/gui

des/jni/index.html

• 書籍(古いが日本語の唯一のも)– 「JNI Java Native Interfaceプログラミング」

(ピアソン・エデュケーション刊、1998年)

• 拙著Web記事– http://www.02.246.ne.jp/~torutk/javahow2/jni.h

tml

Page 20: Jjug night seminar201208_lt_cxxからjvm起動

ご清聴を感謝します

このスライドが出るということは、しゃべりが早すぎだ!