SlideShare una empresa de Scribd logo
1 de 54
Descargar para leer sin conexión
JNIプログラミング

  餃子のまち 宇都宮
    村沢 邦夫
JNIとは?
• Java Native Interface
• Javaからネイティブコードを、またはネイティブコード
  からJavaを利用するための仕組み
  (ネイティブコードは基本的に C/C++ を想定)
• Javaコードとネイティブコードを分離
  (Javaから直接ネイティブコードは呼ばない。呼び出し
  たい関数は、シェアードライブラリとしてラップする)
• JNIプログラミングって、ほとんどCプログラミング(?)
JNIの歴史1
• JDK1.0 JNI以前 不統一時代
Sun - Native Method Interface JVMの実装に依存してしまう。
 (互換性に問題)
Netscape - Java Runtime Interface 移植性は考慮されていた
 が、JVMの実装についての考慮がたりない
Microsoft - Raw Native Interface ガーベッジコレクタと相互的
 に動作しなくてはいけない
JNIの歴史2
• JDK1.1
 3社間で統一 JNI1.1が組み込まれる。すべてのJVM間でバイ
 ナリ互換
 ただしMicrosoftはJNIをサポートせずSunに訴えられる。
• JDK1.2
 JNI1.2 Javaプラットフォームに新機能の組み込みが可能、効
 率的で安定したインタフェースを確立
• JDK1.4
 JNI1.4 呼び出しインタフェースの新しいエントリポイント追
 加、java.nioパッケージのサポート
なぜJNI?
• 既存のライブラリを使いたい
• パフォーマンスを向上させたい
• ハードウェアにアクセスしたい
JNIで出来ること
    メソッドの呼び出し
•
•   フィールドへのアクセス
•   オブジェクトの生成
    例外の発生と捕捉
•
•   JVMのロード
•   スレッドの同期
JNIプログラミング
① Javaコード作成
② javacでクラスファイル生成
③ javahでインクルードファイル生成
④ インクルードファイルを元にC/C++コード作成
⑤ シェアードライブラリ生成
HelloWorld (Javaコード)
$ vi HelloWorld.java
public class HelloWorld {
          static {
                   System.loadLibrary(quot;HelloWorldquot;);
          }

        //Hello World表示
        public native void show();
}

$ javac HelloWorld.java


※System.loadLibraryでネイティブライブラリをロード
※ネイティブメソッドにはnativeキーワードをつける
HelloWorld (ヘッダーファイル)
$ javah HelloWorld
$ cat HelloWorld.h
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class HelloWorld */

#ifndef _Included_HelloWorld
#define _Included_HelloWorld
#ifdef __cplusplus
extern quot;Cquot; {
#endif
/*
 * Class:    HelloWorld
 * Method: show
 * Signature: ()V
 */
JNIEXPORT void JNICALL Java_HelloWorld_show(JNIEnv *, jobject);

#ifdef __cplusplus
}
#endif
#endif
HelloWorld (Cコード)
$ vi HelloWorld.c
#include quot;HelloWorld.hquot;

JNIEXPORT void JNICALL Java_HelloWorld_show(JNIEnv *env, jobject obj)
{
       printf(“Hello Worldn”);
}

$ gcc -fpic -shared -o libHelloWorld.so -I $JAVA_HOME/include
–I $JAVA_HOME/include/linux HelloWorld.c

※シェアードライブラリにすること
HelloWorldのテスト
 $ vi test.java
 public class test {
            public static void main(String[] args) {
                      HelloWorld hello = new HelloWorld();
                      hello.show();
            }
 }

 $ javac test.java


        実行
        $ java test
        Hello World




※作ったシェアードライブラリはロード出来るようにしといてね
 (LD_LIBRARY_PATH)
nativeメソッドの引数
• Javaコード
public native void show()
• Cコード
JNIEXPORT void JNICALL Java_HelloWorld_show(JNIEnv
 *env, jobject obj)

JNIEnv *env - JNIインターフェイスポインタ
  (privateなスレッドデータ、JNI関数へのポインタ)
jobject obj - オブジェクトへの参照
  (staticなメソッドの場合はクラスへの参照)
JNIインターフェイスポインタ




• ネイティブコードはJNI関数を用いてJVMへアクセス
  する。
• JNI関数はJNIインターフェイスポインタを用いて使用
  する。
HelloWorldのまとめ
• Javaコ ード はイ ンタ ーフ ェ イ スの定義
• 処理の実装はCコ ード に
• System.loadLibrary()でネイ ティ ブ ラ イ ブ ラ リ を
  ロ ード
• ネイ ティ ブメ ソ ッ ド にはnativeキーワード
• C から Java へのアク セスはJNI関数
フィールドアクセス
$ vi Sample1.java
public class Sample1 {
          private int data;

         static {
                    System.loadLibrary(quot;Sample1quot;);
         }

         //フィールドに設定
         public native void setData(int val);

         //フィールドから取得
         public native int getData();
}
フィールドに設定
$ vi Sample1.c
#include quot;Sample1.hquot;

// フィールドに設定
JNIEXPORT void JNICALL Java_Sample1_setData(JNIEnv *env, jobject obj, jint val)
{
       jclass clazz;
       jfieldID fid;

        clazz = (*env)->GetObjectClass(env, obj);
        fid = (*env)->GetFieldID(env, clazz, quot;dataquot;, quot;Iquot;);
        (*env)->SetIntField(env, obj, fid, val);
}
フィールドから取得
// フィールドから取得
JNIEXPORT jint JNICALL Java_Sample1_getData(JNIEnv *env, jobject obj)
{
       jclass clazz;
       jfieldID fid;
       jint data;

        clazz = (*env)->GetObjectClass(env, obj);
        fid = (*env)->GetFieldID(env, clazz, quot;dataquot;, quot;Iquot;);
        data = (*env)->GetIntField(env, obj, fid);

        return data;
}
フィールドアクセスのテスト
$ vi test1.java
public class test1 {
          public static void main(String[] args) {
                    Sample1 sample = new Sample1();
                    sample.setData(123);
                    System.out.println(“data = quot; + sample.getData());
          }
}



          実行
          $ java test1
          data = 123
フィールド関連のJNI関数
• jfieldID GetFieldID(JNIEnv *env, jclass clazz, const char *name,
  const char *sig)
  フィールドID取得
• NativeType Get<type>Field(JNIEnv *env, jobject obj, jfieldID
  fieldID)
  フィールド値取得 ex) jint GetIntField()
• void Set<type>Field(JNIEnv *env, jobject obj, jfieldID fieldID,
  NativeType value)
  フィールド値設定 ex) SetIntField()

※スタティックフィールド場合はGetStaticIntFieldIDのようにStatic
が付く。
※ネイティブコードからはJavaアクセス修飾子の制限を受けなくな
 る。
フィールドアクセスのまとめ
  ① クラスを取得
   GetObjectClass()
  ② フィールドIDを取得
   GetFieldID()
  ③ フィールドの値を設定・取得
   Set<type>Field() / Get<type>Field()



※C から Java へのアクセスは JNI関数を使用する。
JNIのネイティブ型
Java                        JNI
byte        8bit            jbyte
short       16bit           jshort
int         32bit           jint
long        64bit           jlong
float       32bit IEEE754   jfloat
double      64bit IEEE754   jdouble
char        16bit UNICODE   jchar
boolean     8bit            jboolean
void                        void
Object                      jobject
Class                       jclass
String                      jstring
                            jarray j<type>Array
配列
Throwable                   jthrowable
                            jvalue
                            jfiledID
                            jmethodID
型シグニチャ
         Java                   シグニチャ
         byte                   B
         short                  S
         int                    I
         long                   J
         float                  F
         double                 D
         char                   C
         boolean                Z
         void                   V

                                L<class>;
         <class>の完全修飾
                                [<type>
         <type>の配列
         メ ソ ッ ド シグニチャ          (引数)戻値


例えば、次のメソッドシグニチャは
long hoge(int n, String s, int[] i) → (ILjava/lang/String;[I)J
メソッドコール・オブジェクト生成
$ vi Sample2.java
public class Sample2 {
           static {
                    System.loadLibrary(quot;Sample2quot;);
           }

         public Sample2() {
         }

         public Sample2(int n) {
                   System.out.println(quot;create object successquot;);
         }

         public void show() {
                    System.out.println(quot;method call successquot;);
         }

         //オブジェクトの生成
         public native void createObject();

         //メソッド呼び出し
         public native void callMethod();
}
オブジェクト生成
$ vi Sample2.c
#include quot;Sample2.hquot;

//オブジェクトの生成
JNIEXPORT void JNICALL Java_Sample2_createObject(JNIEnv *env, jobject obj)
{
       jclass clazz;
       jmethodID mid;
       jobject newObj;

        clazz = (*env)->FindClass(env, quot;Sample2quot;);
        mid = (*env)->GetMethodID(env, clazz, quot;<init>quot;, quot;(I)Vquot;);
        newObj = (*env)->NewObject(env, clazz, mid, 0);
}
メソッドコール
//メソッド呼び出し
JNIEXPORT void JNICALL Java_Sample2_callMethod(JNIEnv *env, jobject obj)
{
       jclass clazz;
       jmethodID mid;

        clazz = (*env)->GetObjectClass(env, obj);
        mid = (*env)->GetMethodID(env, clazz, quot;showquot;, quot;()Vquot;);
        (*env)->CallVoidMethod(env, obj, mid);
}
メソッドコール・オブジェクト生成の
       テスト
$ vi test2.java
public class test2 {
          public static void main(String[] args) {
                    Sample2 sample = new Sample2();
                    sample.createObject();
                    sample.callMethod();
          }
}



          実行
          $ java test2
          create object success
          method call success
クラス・オブジェクト関連のJNI関数
• jclass GetObjectClass(JNIEnv *env, jobject obj)
  オブジェクトのクラスを取得(判定)
• jclass FindClass(JNIEnv *env, const char *name)
  クラスをロード
• jobject NewObject(JNIEnv *env, jclass clazz, jmethodID
  methodID, ...)
  オブジェクトの生成
オブジェクト生成のまとめ
① クラスをロード
 FindClass()
② コンストラクタのIDを取得
 GetMethodID()
③ オブジェクトを生成
 NewObject()
メソッド関連のJNI関数
• jmethodID GetMethodID(JNIEnv *env, jclass clazz, const char
  *name, const char *sig)
  メソッドID取得
• NativeType Call<type>Method(JNIEnv *env, jobject obj, jmethodID
  methodID, ...)
  メソッド呼び出し ex) CallVoidMethod()

※スタティックメソッドの場合はGetStaticIntMethodID()のようにStatic
 が付く。
※ネイティブコードからはJavaアクセス修飾子の制限を受けなくなる。
メソッドコールのまとめ
① クラスを取得
 GetObjectClass()
② メソッドIDを取得
 GetMethodID()
③ メソッド呼び出し
 Call<type>Method()
例外
$ vi Sample3.java
public class Sample3 {
            static {
                         System.loadLibrary(quot;Sample3quot;);
           }

           public static final int MAX = 10;
           private int[] datas = new int[MAX];

           //例外を投げる
           public native void setData(int no, int data) throws ArrayIndexOutOfBoundsException;

           //例外を捕まえる
           public native void showData(int no);

           public int getData(int no) throws ArrayIndexOutOfBoundsException {
                       try {
                                   return datas[no];
                       } catch (ArrayIndexOutOfBoundsException e) {
                                   throw e;
                       }
           }
}
例外を投げる
$ vi Sample3.c
#include quot;Sample3.hquot;

JNIEXPORT void JNICALL Java_Sample3_setData(JNIEnv *env, jobject obj, jint no, jint data)
{
           jclass clazz;
           jfieldID fid;
           jint *dataElems;
           jintArray datas;
           jboolean isCopy;

             clazz = (*env)->GetObjectClass(env, obj);
             fid = (*env)->GetFieldID(env, clazz, quot;datasquot;, quot;[Iquot;);
             datas = (*env)->GetObjectField(env, obj, fid);
             dataElems = (*env)->GetIntArrayElements(env, datas, &isCopy);

             if (no < 0 || no >= Sample3_MAX) {
                            //例外投げる
                            jclass clazz;
                            jmethodID mid;
                            jthrowable throwObj;

                          clazz = (*env)->FindClass(env, quot;java/lang/ArrayIndexOutOfBoundsExceptionquot;);
                          mid = (*env)->GetMethodID(env, clazz, quot;<init>quot;, quot;()Vquot;);
                          throwObj = (*env)->NewObject(env, clazz, mid);
                          (*env)->Throw(env, throwObj);
                          return;
             }

             dataElems[no] = data;
             if (isCopy == JNI_TRUE) {
                          (*env)->ReleaseIntArrayElements(env, datas, dataElems, 0);
             }
}
例外を捕まえる
JNIEXPORT void JNICALL Java_Sample3_showData(JNIEnv *env, jobject obj, jint no)
{
       jclass clazz;
       jmethodID mid;
       jint data;
       jthrowable throwObj;

        clazz = (*env)->GetObjectClass(env, obj);
        mid = (*env)->GetMethodID(env, clazz, quot;getDataquot;, quot;(I)Iquot;);
        data = (*env)->CallIntMethod(env, obj, mid, no);

        //例外を捕まえる
        throwObj = (*env)->ExceptionOccurred(env);
        if (throwObj != NULL) {
                 (*env)->ExceptionDescribe(env);
                 (*env)->ExceptionClear(env);
                 return;
        }

        printf(quot;native data = %dnquot;, data);
}
例外のテスト(1)
$ vi test3.java
public class test3 {
          public static void main(String[] args) {
                    Sample2 sample = new Sample2();
                    try {
                             sample.setData(5, 123);
                             System.out.println(quot;data = quot; + sample.getData(5));
                             sample.setData(10, 456);
                    } catch (ArrayIndexOutOfBoundsException e) {
                             e.printStackTrace();
                    }
                    sample.showData(5);
                    sample.showData(10);
          }
}
例外のテスト(2)
実行
$ java test3
data = 123
java.lang.ArrayIndexOutOfBoundsException
    at Sample2.setData(Native Method)
    at test2.main(test2.java:7)
native data = 123
Exception in thread quot;mainquot; java.lang.ArrayIndexOutOfBoundsException
    at Sample2.getData(Sample2.java:14)
    at Sample2.showData(Native Method)
    at test2.main(test2.java:12)
例外関連のJNI関数
• jint Throw(JNIEnv *env, jthrowable obj)
  例外を投げる
• jthrowable ExceptionOccurred(JNIEnv *env)
  例外が発生してるか調べる
• void ExceptionDescribe(JNIEnv *env)
  例外のスタックトレースをプリント
• void ExceptionClear(JNIEnv *env)
  例外のクリア

※Throw()しても実際に例外を投げるのはネイティブメソッドを抜
 けた後
例外のまとめ(投げる)
① クラスをロード
 FindClass()
② コンストラクタのIDを取得
 GetMethodID()
③ オブジェクトを生成
 NewObject()
④ 例外を投げる
 Throw()
例外のまとめ(捕まえる)
① 例外が発生しているが調べる。
  ExceptionOccurred()
② 例外処理
③ 例外をクリア
  ExceptionClear()
CからJavaを呼ぶ
$ vi Sample4.java
public class Sample4 {
          public void show() {
                   System.out.println(“JVM Worldquot;);
          }
}
CからJavaを呼ぶ(Cコード)(1)
$vi Sample4.c
#include <jni.h>

int main(int argc, char *argv[]) {
           JNIEnv *env;
           JavaVM *jvm;
           JavaVMInitArgs vm_args;

         jclass clazz;
         jobject obj;
         jmethodID mid;

         jint ret;

         vm_args.version = JNI_VERSION_1_2;

         JNI_GetDefaultJavaVMInitArgs(&vm_args);

         ret = JNI_CreateJavaVM(&jvm, (void **) &env, &vm_args);
         if (ret < 0) {
                    fprintf(stderr, quot;Can't create JVM.quot;);
                    return 1;
         }
CからJavaを呼ぶ(Cコード)(2)
    clazz = (*env)->FindClass(env, quot;Sample3quot;);

    mid = (*env)->GetMethodID(env, clazz, quot;<init>quot;, quot;()Vquot;);

    obj = (*env)->NewObject(env, clazz, mid);

    mid = (*env)->GetMethodID(env, clazz, quot;showquot;, quot;()Vquot;);

    (*env)->CallVoidMethod(env, obj, mid);

    (*jvm)->DestroyJavaVM(jvm);

    return 0;
}


    実行
    $ ./Sample4
    JVM World
JNIの起動(呼び出し)API
• jint JNI_CreateJavaVM(JavaVM **p_vm, JNIEnv **p_env,
  void *vm_args)
  JVMのロード、初期化
• jint DestroyJavaVM(JavaVM *vm)
  JVMのアンロード
• jint JNI_GetDefaultJavaVMInitArgs(void *vm_args)
  JVM初期化の為のデフォルト値取得
CからJavaを呼ぶのまとめ
① JVMの初期化データを設定
  JNI_GetDefaultJavaVMInitArgs()
② JVMのロード・初期化
  JNI_CreateJavaVM()
③ JNI関数を用いて処理
④ JVMのアンロード
  DestroyJavaVM()
文字列
$ vi Sample5.java
public class Sample5 {
          static {
                   System.loadLibrary(quot;Sample5quot;);
          }

        //Javaからの文字列表示
        public native void show(String str);

        //Cから文字列取得
        public native String getMessage();
}
文字列(Javaから)
$ vi Sample5.c
#include <iconv.h>
#include quot;Sample5.hquot;

// Javaからの文字列表示
JNIEXPORT void JNICALL Java_Sample5_show(JNIEnv *env, jobject obj, jstring str)
{
         const char *msg;
         jboolean isCopy;

           msg = (*env)->GetStringUTFChars(env, str, &isCopy);
           if (isCopy == JNI_TRUE) {
                       iconv_t cd;
                       size_t isize, osize;
                       char euc[25];
                       char *obuf = euc;

                       isize = (*env)->GetStringUTFLength(env, str) * 2;
                       osize = sizeof(euc);
                       cd = iconv_open(quot;euc-jpquot;, quot;utf-8quot;);
                       iconv(cd, &msg, &isize, &obuf, &osize);
                       printf(quot;%snquot;, euc);
                       (*env)->ReleaseStringUTFChars(env, str, msg);
                       iconv_close(cd);
           }
}
文字列(Cから)
// Cから文字列取得
JNIEXPORT jstring JNICALL Java_Sample5_getMessage(JNIEnv *env, jobject obj)
{
         const char *msg = quot;シー ワールドquot;;
         char utf[25];
         char *obuf = utf;
         iconv_t cd;
         size_t isize, osize;

          isize = strlen(msg);
          osize = sizeof(utf);
          memset(utf, 0, osize);

          cd = iconv_open(quot;utf-8quot;, quot;euc-jpquot;);
          iconv(cd, &msg, &isize, &obuf, &osize);
          iconv_close(cd);

          return (*env)->NewStringUTF(env, utf);
}
文字列のテスト
$ vi test5.java
public class test5 {
          public static void main(String[] args) {
                    Sample5 sample = new Sample5();
                    sample.show(quot;ジャバ ワールドquot;);
                    System.out.println(sample.getMessage());
          }
}


         実行
         $ java test5
         ジャバ ワールド
         シー ワールド
文字列関連のJNI関数
• jstring NewStringUTF(JNIEnv *env, const char *bytes)
  UTF-8の文字列からStringオブジェクトを生成
• const char* GetStringUTFChars(JNIEnv *env, jstring string,
  jboolean *isCopy)
  StringオブジェクトからUTF-8文字列を取得
• void ReleaseStringUTFChars(JNIEnv *env, jstring string,
  const char *utf)
  GetStringUTFChars()で取得した文字列を開放
• jsize GetStringUTFLength(JNIEnv *env, jstring string)
  文字列の長さを取得

※C側で扱える文字コードに変換する必要あり
 (今回はiconvを使用した。)
文字列のまとめ(Javaから)
① Stringオブジェクトから文字列を取得
 GetStringUTFChars()
② Cでの文字コードへ変換
 (今回はiconvを使った)
③ 文字列を開放
 ReleaseStringUTFChars()
文字列のまとめ(Cから)
① Javaの文字コードへ変換
 (今回はiconvを使った)
② Stringオブジェクトを生成
 NewStringUTF()
スレッドの同期方法
• nativeメソッドにsynchronizedキーワード
• JNI関数 MonitorEnter/MonitorExit を使用
  (Java synchronized文で囲むのと同等)
• JNI関数 Call<type>Method を用いて wait/notify
  メソッドを呼び出す
今日のまとめ
    処理の実装はCコード側
•
•   C から Java へのアクセスはJNI関数
•   やっぱりCプログラミングだった(?)
    JNIプログラミングは難しくない(?)
•
•   でも面倒だ
参考文献
• JNI : Java Native Interfaceプログラミング
  著者 ロブ・ゴードン 出版社 ピアソン

• JDKドキュメント
http://java.sun.com/j2se/1.4/ja/docs/ja/guide/jni/index.html
おわり


      Ver.1.0 2002/08/22
      Ver.1.1 2002/08/27

Más contenido relacionado

La actualidad más candente (14)

Sc2009autumn 次世代Daoフレームワーク Doma
Sc2009autumn 次世代Daoフレームワーク DomaSc2009autumn 次世代Daoフレームワーク Doma
Sc2009autumn 次世代Daoフレームワーク Doma
 
4200 Kte7.0 Training V1.0
4200 Kte7.0 Training V1.04200 Kte7.0 Training V1.0
4200 Kte7.0 Training V1.0
 
What Can Compilers Do for Us?
What Can Compilers Do for Us?What Can Compilers Do for Us?
What Can Compilers Do for Us?
 
Manabeh
ManabehManabeh
Manabeh
 
Vidéo approche en immobilier
Vidéo approche en immobilierVidéo approche en immobilier
Vidéo approche en immobilier
 
11X1 T08 03 rules for differentiation
11X1 T08 03 rules for differentiation11X1 T08 03 rules for differentiation
11X1 T08 03 rules for differentiation
 
Developing Google Glass
Developing Google GlassDeveloping Google Glass
Developing Google Glass
 
Fluent Refactoring (Cascadia Ruby Conf 2013)
Fluent Refactoring (Cascadia Ruby Conf 2013)Fluent Refactoring (Cascadia Ruby Conf 2013)
Fluent Refactoring (Cascadia Ruby Conf 2013)
 
C++ interview questions
C++ interview questionsC++ interview questions
C++ interview questions
 
【12-B-4】 並列処理開発を支援するコンパイラの機能
【12-B-4】 並列処理開発を支援するコンパイラの機能【12-B-4】 並列処理開発を支援するコンパイラの機能
【12-B-4】 並列処理開発を支援するコンパイラの機能
 
Sk.php
Sk.phpSk.php
Sk.php
 
023 vimtamogudu
023 vimtamogudu023 vimtamogudu
023 vimtamogudu
 
Trabalho 3ano
Trabalho 3anoTrabalho 3ano
Trabalho 3ano
 
SQLAlchemy Seminar
SQLAlchemy SeminarSQLAlchemy Seminar
SQLAlchemy Seminar
 

Similar a Programming JNI

技術トレンディセミナー フレームワークとしてのTrac
技術トレンディセミナー フレームワークとしてのTrac技術トレンディセミナー フレームワークとしてのTrac
技術トレンディセミナー フレームワークとしてのTrac
terada
 
JSplash - Adobe MAX 2009
JSplash - Adobe MAX 2009JSplash - Adobe MAX 2009
JSplash - Adobe MAX 2009
gyuque
 
WindowsユーザのためのはじめてのPerlプログラミング
WindowsユーザのためのはじめてのPerlプログラミングWindowsユーザのためのはじめてのPerlプログラミング
WindowsユーザのためのはじめてのPerlプログラミング
Yosuke HASEGAWA
 
How To Create Custom DSLs By PHP
How To Create Custom DSLs By PHPHow To Create Custom DSLs By PHP
How To Create Custom DSLs By PHP
Atsuhiro Kubo
 

Similar a Programming JNI (20)

object-shapes
object-shapesobject-shapes
object-shapes
 
Grails紹介
Grails紹介Grails紹介
Grails紹介
 
技術トレンディセミナー フレームワークとしてのTrac
技術トレンディセミナー フレームワークとしてのTrac技術トレンディセミナー フレームワークとしてのTrac
技術トレンディセミナー フレームワークとしてのTrac
 
Reloaded
ReloadedReloaded
Reloaded
 
JSplash - Adobe MAX 2009
JSplash - Adobe MAX 2009JSplash - Adobe MAX 2009
JSplash - Adobe MAX 2009
 
Revisited
RevisitedRevisited
Revisited
 
Jslunch6
Jslunch6Jslunch6
Jslunch6
 
Shibuya.abc - Gnashで遊ぼう
Shibuya.abc - Gnashで遊ぼうShibuya.abc - Gnashで遊ぼう
Shibuya.abc - Gnashで遊ぼう
 
Y Map Mashup Camp
Y Map Mashup CampY Map Mashup Camp
Y Map Mashup Camp
 
DOSUG Intro to JQuery JavaScript Framework
DOSUG Intro to JQuery JavaScript FrameworkDOSUG Intro to JQuery JavaScript Framework
DOSUG Intro to JQuery JavaScript Framework
 
jQuery Internals + Cool Stuff
jQuery Internals + Cool StuffjQuery Internals + Cool Stuff
jQuery Internals + Cool Stuff
 
GAE/J 開発環境でJDO入門
GAE/J 開発環境でJDO入門GAE/J 開発環境でJDO入門
GAE/J 開発環境でJDO入門
 
【13 C 2】デベロッパーに贈る!M-V-VMパターンで造るWPFアプリケーション
【13 C 2】デベロッパーに贈る!M-V-VMパターンで造るWPFアプリケーション【13 C 2】デベロッパーに贈る!M-V-VMパターンで造るWPFアプリケーション
【13 C 2】デベロッパーに贈る!M-V-VMパターンで造るWPFアプリケーション
 
JSARToolKit / LiveChromaKey / LivePointers - Next gen of AR
JSARToolKit / LiveChromaKey / LivePointers - Next gen of ARJSARToolKit / LiveChromaKey / LivePointers - Next gen of AR
JSARToolKit / LiveChromaKey / LivePointers - Next gen of AR
 
dRuby
dRubydRuby
dRuby
 
Ruby Postgres
Ruby PostgresRuby Postgres
Ruby Postgres
 
WindowsユーザのためのはじめてのPerlプログラミング
WindowsユーザのためのはじめてのPerlプログラミングWindowsユーザのためのはじめてのPerlプログラミング
WindowsユーザのためのはじめてのPerlプログラミング
 
Mgd08 lab01
Mgd08 lab01Mgd08 lab01
Mgd08 lab01
 
樽家昌也 (日本Rubyの会)
樽家昌也 (日本Rubyの会) 樽家昌也 (日本Rubyの会)
樽家昌也 (日本Rubyの会)
 
How To Create Custom DSLs By PHP
How To Create Custom DSLs By PHPHow To Create Custom DSLs By PHP
How To Create Custom DSLs By PHP
 

Último

+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
?#DUbAI#??##{{(☎️+971_581248768%)**%*]'#abortion pills for sale in dubai@
 
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers:  A Deep Dive into Serverless Spatial Data and FMECloud Frontiers:  A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Safe Software
 

Último (20)

Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot TakeoffStrategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
 
Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...
 
Boost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfBoost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdf
 
MINDCTI Revenue Release Quarter One 2024
MINDCTI Revenue Release Quarter One 2024MINDCTI Revenue Release Quarter One 2024
MINDCTI Revenue Release Quarter One 2024
 
Polkadot JAM Slides - Token2049 - By Dr. Gavin Wood
Polkadot JAM Slides - Token2049 - By Dr. Gavin WoodPolkadot JAM Slides - Token2049 - By Dr. Gavin Wood
Polkadot JAM Slides - Token2049 - By Dr. Gavin Wood
 
Manulife - Insurer Transformation Award 2024
Manulife - Insurer Transformation Award 2024Manulife - Insurer Transformation Award 2024
Manulife - Insurer Transformation Award 2024
 
Emergent Methods: Multi-lingual narrative tracking in the news - real-time ex...
Emergent Methods: Multi-lingual narrative tracking in the news - real-time ex...Emergent Methods: Multi-lingual narrative tracking in the news - real-time ex...
Emergent Methods: Multi-lingual narrative tracking in the news - real-time ex...
 
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
 
TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data DiscoveryTrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
 
Strategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a FresherStrategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a Fresher
 
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
 
EMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWER
EMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWEREMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWER
EMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWER
 
Artificial Intelligence Chap.5 : Uncertainty
Artificial Intelligence Chap.5 : UncertaintyArtificial Intelligence Chap.5 : Uncertainty
Artificial Intelligence Chap.5 : Uncertainty
 
AWS Community Day CPH - Three problems of Terraform
AWS Community Day CPH - Three problems of TerraformAWS Community Day CPH - Three problems of Terraform
AWS Community Day CPH - Three problems of Terraform
 
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
 
"I see eyes in my soup": How Delivery Hero implemented the safety system for ...
"I see eyes in my soup": How Delivery Hero implemented the safety system for ..."I see eyes in my soup": How Delivery Hero implemented the safety system for ...
"I see eyes in my soup": How Delivery Hero implemented the safety system for ...
 
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, AdobeApidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
 
Apidays Singapore 2024 - Scalable LLM APIs for AI and Generative AI Applicati...
Apidays Singapore 2024 - Scalable LLM APIs for AI and Generative AI Applicati...Apidays Singapore 2024 - Scalable LLM APIs for AI and Generative AI Applicati...
Apidays Singapore 2024 - Scalable LLM APIs for AI and Generative AI Applicati...
 
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers:  A Deep Dive into Serverless Spatial Data and FMECloud Frontiers:  A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
 
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
 

Programming JNI

  • 2. JNIとは? • Java Native Interface • Javaからネイティブコードを、またはネイティブコード からJavaを利用するための仕組み (ネイティブコードは基本的に C/C++ を想定) • Javaコードとネイティブコードを分離 (Javaから直接ネイティブコードは呼ばない。呼び出し たい関数は、シェアードライブラリとしてラップする) • JNIプログラミングって、ほとんどCプログラミング(?)
  • 3. JNIの歴史1 • JDK1.0 JNI以前 不統一時代 Sun - Native Method Interface JVMの実装に依存してしまう。 (互換性に問題) Netscape - Java Runtime Interface 移植性は考慮されていた が、JVMの実装についての考慮がたりない Microsoft - Raw Native Interface ガーベッジコレクタと相互的 に動作しなくてはいけない
  • 4. JNIの歴史2 • JDK1.1 3社間で統一 JNI1.1が組み込まれる。すべてのJVM間でバイ ナリ互換 ただしMicrosoftはJNIをサポートせずSunに訴えられる。 • JDK1.2 JNI1.2 Javaプラットフォームに新機能の組み込みが可能、効 率的で安定したインタフェースを確立 • JDK1.4 JNI1.4 呼び出しインタフェースの新しいエントリポイント追 加、java.nioパッケージのサポート
  • 6. JNIで出来ること メソッドの呼び出し • • フィールドへのアクセス • オブジェクトの生成 例外の発生と捕捉 • • JVMのロード • スレッドの同期
  • 7. JNIプログラミング ① Javaコード作成 ② javacでクラスファイル生成 ③ javahでインクルードファイル生成 ④ インクルードファイルを元にC/C++コード作成 ⑤ シェアードライブラリ生成
  • 8. HelloWorld (Javaコード) $ vi HelloWorld.java public class HelloWorld { static { System.loadLibrary(quot;HelloWorldquot;); } //Hello World表示 public native void show(); } $ javac HelloWorld.java ※System.loadLibraryでネイティブライブラリをロード ※ネイティブメソッドにはnativeキーワードをつける
  • 9. HelloWorld (ヘッダーファイル) $ javah HelloWorld $ cat HelloWorld.h /* DO NOT EDIT THIS FILE - it is machine generated */ #include <jni.h> /* Header for class HelloWorld */ #ifndef _Included_HelloWorld #define _Included_HelloWorld #ifdef __cplusplus extern quot;Cquot; { #endif /* * Class: HelloWorld * Method: show * Signature: ()V */ JNIEXPORT void JNICALL Java_HelloWorld_show(JNIEnv *, jobject); #ifdef __cplusplus } #endif #endif
  • 10. HelloWorld (Cコード) $ vi HelloWorld.c #include quot;HelloWorld.hquot; JNIEXPORT void JNICALL Java_HelloWorld_show(JNIEnv *env, jobject obj) { printf(“Hello Worldn”); } $ gcc -fpic -shared -o libHelloWorld.so -I $JAVA_HOME/include –I $JAVA_HOME/include/linux HelloWorld.c ※シェアードライブラリにすること
  • 11. HelloWorldのテスト $ vi test.java public class test { public static void main(String[] args) { HelloWorld hello = new HelloWorld(); hello.show(); } } $ javac test.java 実行 $ java test Hello World ※作ったシェアードライブラリはロード出来るようにしといてね (LD_LIBRARY_PATH)
  • 12. nativeメソッドの引数 • Javaコード public native void show() • Cコード JNIEXPORT void JNICALL Java_HelloWorld_show(JNIEnv *env, jobject obj) JNIEnv *env - JNIインターフェイスポインタ (privateなスレッドデータ、JNI関数へのポインタ) jobject obj - オブジェクトへの参照 (staticなメソッドの場合はクラスへの参照)
  • 13. JNIインターフェイスポインタ • ネイティブコードはJNI関数を用いてJVMへアクセス する。 • JNI関数はJNIインターフェイスポインタを用いて使用 する。
  • 14. HelloWorldのまとめ • Javaコ ード はイ ンタ ーフ ェ イ スの定義 • 処理の実装はCコ ード に • System.loadLibrary()でネイ ティ ブ ラ イ ブ ラ リ を ロ ード • ネイ ティ ブメ ソ ッ ド にはnativeキーワード • C から Java へのアク セスはJNI関数
  • 15. フィールドアクセス $ vi Sample1.java public class Sample1 { private int data; static { System.loadLibrary(quot;Sample1quot;); } //フィールドに設定 public native void setData(int val); //フィールドから取得 public native int getData(); }
  • 16. フィールドに設定 $ vi Sample1.c #include quot;Sample1.hquot; // フィールドに設定 JNIEXPORT void JNICALL Java_Sample1_setData(JNIEnv *env, jobject obj, jint val) { jclass clazz; jfieldID fid; clazz = (*env)->GetObjectClass(env, obj); fid = (*env)->GetFieldID(env, clazz, quot;dataquot;, quot;Iquot;); (*env)->SetIntField(env, obj, fid, val); }
  • 17. フィールドから取得 // フィールドから取得 JNIEXPORT jint JNICALL Java_Sample1_getData(JNIEnv *env, jobject obj) { jclass clazz; jfieldID fid; jint data; clazz = (*env)->GetObjectClass(env, obj); fid = (*env)->GetFieldID(env, clazz, quot;dataquot;, quot;Iquot;); data = (*env)->GetIntField(env, obj, fid); return data; }
  • 18. フィールドアクセスのテスト $ vi test1.java public class test1 { public static void main(String[] args) { Sample1 sample = new Sample1(); sample.setData(123); System.out.println(“data = quot; + sample.getData()); } } 実行 $ java test1 data = 123
  • 19. フィールド関連のJNI関数 • jfieldID GetFieldID(JNIEnv *env, jclass clazz, const char *name, const char *sig) フィールドID取得 • NativeType Get<type>Field(JNIEnv *env, jobject obj, jfieldID fieldID) フィールド値取得 ex) jint GetIntField() • void Set<type>Field(JNIEnv *env, jobject obj, jfieldID fieldID, NativeType value) フィールド値設定 ex) SetIntField() ※スタティックフィールド場合はGetStaticIntFieldIDのようにStatic が付く。 ※ネイティブコードからはJavaアクセス修飾子の制限を受けなくな る。
  • 20. フィールドアクセスのまとめ ① クラスを取得 GetObjectClass() ② フィールドIDを取得 GetFieldID() ③ フィールドの値を設定・取得 Set<type>Field() / Get<type>Field() ※C から Java へのアクセスは JNI関数を使用する。
  • 21. JNIのネイティブ型 Java JNI byte 8bit jbyte short 16bit jshort int 32bit jint long 64bit jlong float 32bit IEEE754 jfloat double 64bit IEEE754 jdouble char 16bit UNICODE jchar boolean 8bit jboolean void void Object jobject Class jclass String jstring jarray j<type>Array 配列 Throwable jthrowable jvalue jfiledID jmethodID
  • 22. 型シグニチャ Java シグニチャ byte B short S int I long J float F double D char C boolean Z void V L<class>; <class>の完全修飾 [<type> <type>の配列 メ ソ ッ ド シグニチャ (引数)戻値 例えば、次のメソッドシグニチャは long hoge(int n, String s, int[] i) → (ILjava/lang/String;[I)J
  • 23. メソッドコール・オブジェクト生成 $ vi Sample2.java public class Sample2 { static { System.loadLibrary(quot;Sample2quot;); } public Sample2() { } public Sample2(int n) { System.out.println(quot;create object successquot;); } public void show() { System.out.println(quot;method call successquot;); } //オブジェクトの生成 public native void createObject(); //メソッド呼び出し public native void callMethod(); }
  • 24. オブジェクト生成 $ vi Sample2.c #include quot;Sample2.hquot; //オブジェクトの生成 JNIEXPORT void JNICALL Java_Sample2_createObject(JNIEnv *env, jobject obj) { jclass clazz; jmethodID mid; jobject newObj; clazz = (*env)->FindClass(env, quot;Sample2quot;); mid = (*env)->GetMethodID(env, clazz, quot;<init>quot;, quot;(I)Vquot;); newObj = (*env)->NewObject(env, clazz, mid, 0); }
  • 25. メソッドコール //メソッド呼び出し JNIEXPORT void JNICALL Java_Sample2_callMethod(JNIEnv *env, jobject obj) { jclass clazz; jmethodID mid; clazz = (*env)->GetObjectClass(env, obj); mid = (*env)->GetMethodID(env, clazz, quot;showquot;, quot;()Vquot;); (*env)->CallVoidMethod(env, obj, mid); }
  • 26. メソッドコール・オブジェクト生成の テスト $ vi test2.java public class test2 { public static void main(String[] args) { Sample2 sample = new Sample2(); sample.createObject(); sample.callMethod(); } } 実行 $ java test2 create object success method call success
  • 27. クラス・オブジェクト関連のJNI関数 • jclass GetObjectClass(JNIEnv *env, jobject obj) オブジェクトのクラスを取得(判定) • jclass FindClass(JNIEnv *env, const char *name) クラスをロード • jobject NewObject(JNIEnv *env, jclass clazz, jmethodID methodID, ...) オブジェクトの生成
  • 28. オブジェクト生成のまとめ ① クラスをロード FindClass() ② コンストラクタのIDを取得 GetMethodID() ③ オブジェクトを生成 NewObject()
  • 29. メソッド関連のJNI関数 • jmethodID GetMethodID(JNIEnv *env, jclass clazz, const char *name, const char *sig) メソッドID取得 • NativeType Call<type>Method(JNIEnv *env, jobject obj, jmethodID methodID, ...) メソッド呼び出し ex) CallVoidMethod() ※スタティックメソッドの場合はGetStaticIntMethodID()のようにStatic が付く。 ※ネイティブコードからはJavaアクセス修飾子の制限を受けなくなる。
  • 30. メソッドコールのまとめ ① クラスを取得 GetObjectClass() ② メソッドIDを取得 GetMethodID() ③ メソッド呼び出し Call<type>Method()
  • 31. 例外 $ vi Sample3.java public class Sample3 { static { System.loadLibrary(quot;Sample3quot;); } public static final int MAX = 10; private int[] datas = new int[MAX]; //例外を投げる public native void setData(int no, int data) throws ArrayIndexOutOfBoundsException; //例外を捕まえる public native void showData(int no); public int getData(int no) throws ArrayIndexOutOfBoundsException { try { return datas[no]; } catch (ArrayIndexOutOfBoundsException e) { throw e; } } }
  • 32. 例外を投げる $ vi Sample3.c #include quot;Sample3.hquot; JNIEXPORT void JNICALL Java_Sample3_setData(JNIEnv *env, jobject obj, jint no, jint data) { jclass clazz; jfieldID fid; jint *dataElems; jintArray datas; jboolean isCopy; clazz = (*env)->GetObjectClass(env, obj); fid = (*env)->GetFieldID(env, clazz, quot;datasquot;, quot;[Iquot;); datas = (*env)->GetObjectField(env, obj, fid); dataElems = (*env)->GetIntArrayElements(env, datas, &isCopy); if (no < 0 || no >= Sample3_MAX) { //例外投げる jclass clazz; jmethodID mid; jthrowable throwObj; clazz = (*env)->FindClass(env, quot;java/lang/ArrayIndexOutOfBoundsExceptionquot;); mid = (*env)->GetMethodID(env, clazz, quot;<init>quot;, quot;()Vquot;); throwObj = (*env)->NewObject(env, clazz, mid); (*env)->Throw(env, throwObj); return; } dataElems[no] = data; if (isCopy == JNI_TRUE) { (*env)->ReleaseIntArrayElements(env, datas, dataElems, 0); } }
  • 33. 例外を捕まえる JNIEXPORT void JNICALL Java_Sample3_showData(JNIEnv *env, jobject obj, jint no) { jclass clazz; jmethodID mid; jint data; jthrowable throwObj; clazz = (*env)->GetObjectClass(env, obj); mid = (*env)->GetMethodID(env, clazz, quot;getDataquot;, quot;(I)Iquot;); data = (*env)->CallIntMethod(env, obj, mid, no); //例外を捕まえる throwObj = (*env)->ExceptionOccurred(env); if (throwObj != NULL) { (*env)->ExceptionDescribe(env); (*env)->ExceptionClear(env); return; } printf(quot;native data = %dnquot;, data); }
  • 34. 例外のテスト(1) $ vi test3.java public class test3 { public static void main(String[] args) { Sample2 sample = new Sample2(); try { sample.setData(5, 123); System.out.println(quot;data = quot; + sample.getData(5)); sample.setData(10, 456); } catch (ArrayIndexOutOfBoundsException e) { e.printStackTrace(); } sample.showData(5); sample.showData(10); } }
  • 35. 例外のテスト(2) 実行 $ java test3 data = 123 java.lang.ArrayIndexOutOfBoundsException at Sample2.setData(Native Method) at test2.main(test2.java:7) native data = 123 Exception in thread quot;mainquot; java.lang.ArrayIndexOutOfBoundsException at Sample2.getData(Sample2.java:14) at Sample2.showData(Native Method) at test2.main(test2.java:12)
  • 36. 例外関連のJNI関数 • jint Throw(JNIEnv *env, jthrowable obj) 例外を投げる • jthrowable ExceptionOccurred(JNIEnv *env) 例外が発生してるか調べる • void ExceptionDescribe(JNIEnv *env) 例外のスタックトレースをプリント • void ExceptionClear(JNIEnv *env) 例外のクリア ※Throw()しても実際に例外を投げるのはネイティブメソッドを抜 けた後
  • 37. 例外のまとめ(投げる) ① クラスをロード FindClass() ② コンストラクタのIDを取得 GetMethodID() ③ オブジェクトを生成 NewObject() ④ 例外を投げる Throw()
  • 38. 例外のまとめ(捕まえる) ① 例外が発生しているが調べる。 ExceptionOccurred() ② 例外処理 ③ 例外をクリア ExceptionClear()
  • 39. CからJavaを呼ぶ $ vi Sample4.java public class Sample4 { public void show() { System.out.println(“JVM Worldquot;); } }
  • 40. CからJavaを呼ぶ(Cコード)(1) $vi Sample4.c #include <jni.h> int main(int argc, char *argv[]) { JNIEnv *env; JavaVM *jvm; JavaVMInitArgs vm_args; jclass clazz; jobject obj; jmethodID mid; jint ret; vm_args.version = JNI_VERSION_1_2; JNI_GetDefaultJavaVMInitArgs(&vm_args); ret = JNI_CreateJavaVM(&jvm, (void **) &env, &vm_args); if (ret < 0) { fprintf(stderr, quot;Can't create JVM.quot;); return 1; }
  • 41. CからJavaを呼ぶ(Cコード)(2) clazz = (*env)->FindClass(env, quot;Sample3quot;); mid = (*env)->GetMethodID(env, clazz, quot;<init>quot;, quot;()Vquot;); obj = (*env)->NewObject(env, clazz, mid); mid = (*env)->GetMethodID(env, clazz, quot;showquot;, quot;()Vquot;); (*env)->CallVoidMethod(env, obj, mid); (*jvm)->DestroyJavaVM(jvm); return 0; } 実行 $ ./Sample4 JVM World
  • 42. JNIの起動(呼び出し)API • jint JNI_CreateJavaVM(JavaVM **p_vm, JNIEnv **p_env, void *vm_args) JVMのロード、初期化 • jint DestroyJavaVM(JavaVM *vm) JVMのアンロード • jint JNI_GetDefaultJavaVMInitArgs(void *vm_args) JVM初期化の為のデフォルト値取得
  • 43. CからJavaを呼ぶのまとめ ① JVMの初期化データを設定 JNI_GetDefaultJavaVMInitArgs() ② JVMのロード・初期化 JNI_CreateJavaVM() ③ JNI関数を用いて処理 ④ JVMのアンロード DestroyJavaVM()
  • 44. 文字列 $ vi Sample5.java public class Sample5 { static { System.loadLibrary(quot;Sample5quot;); } //Javaからの文字列表示 public native void show(String str); //Cから文字列取得 public native String getMessage(); }
  • 45. 文字列(Javaから) $ vi Sample5.c #include <iconv.h> #include quot;Sample5.hquot; // Javaからの文字列表示 JNIEXPORT void JNICALL Java_Sample5_show(JNIEnv *env, jobject obj, jstring str) { const char *msg; jboolean isCopy; msg = (*env)->GetStringUTFChars(env, str, &isCopy); if (isCopy == JNI_TRUE) { iconv_t cd; size_t isize, osize; char euc[25]; char *obuf = euc; isize = (*env)->GetStringUTFLength(env, str) * 2; osize = sizeof(euc); cd = iconv_open(quot;euc-jpquot;, quot;utf-8quot;); iconv(cd, &msg, &isize, &obuf, &osize); printf(quot;%snquot;, euc); (*env)->ReleaseStringUTFChars(env, str, msg); iconv_close(cd); } }
  • 46. 文字列(Cから) // Cから文字列取得 JNIEXPORT jstring JNICALL Java_Sample5_getMessage(JNIEnv *env, jobject obj) { const char *msg = quot;シー ワールドquot;; char utf[25]; char *obuf = utf; iconv_t cd; size_t isize, osize; isize = strlen(msg); osize = sizeof(utf); memset(utf, 0, osize); cd = iconv_open(quot;utf-8quot;, quot;euc-jpquot;); iconv(cd, &msg, &isize, &obuf, &osize); iconv_close(cd); return (*env)->NewStringUTF(env, utf); }
  • 47. 文字列のテスト $ vi test5.java public class test5 { public static void main(String[] args) { Sample5 sample = new Sample5(); sample.show(quot;ジャバ ワールドquot;); System.out.println(sample.getMessage()); } } 実行 $ java test5 ジャバ ワールド シー ワールド
  • 48. 文字列関連のJNI関数 • jstring NewStringUTF(JNIEnv *env, const char *bytes) UTF-8の文字列からStringオブジェクトを生成 • const char* GetStringUTFChars(JNIEnv *env, jstring string, jboolean *isCopy) StringオブジェクトからUTF-8文字列を取得 • void ReleaseStringUTFChars(JNIEnv *env, jstring string, const char *utf) GetStringUTFChars()で取得した文字列を開放 • jsize GetStringUTFLength(JNIEnv *env, jstring string) 文字列の長さを取得 ※C側で扱える文字コードに変換する必要あり (今回はiconvを使用した。)
  • 49. 文字列のまとめ(Javaから) ① Stringオブジェクトから文字列を取得 GetStringUTFChars() ② Cでの文字コードへ変換 (今回はiconvを使った) ③ 文字列を開放 ReleaseStringUTFChars()
  • 51. スレッドの同期方法 • nativeメソッドにsynchronizedキーワード • JNI関数 MonitorEnter/MonitorExit を使用 (Java synchronized文で囲むのと同等) • JNI関数 Call<type>Method を用いて wait/notify メソッドを呼び出す
  • 52. 今日のまとめ 処理の実装はCコード側 • • C から Java へのアクセスはJNI関数 • やっぱりCプログラミングだった(?) JNIプログラミングは難しくない(?) • • でも面倒だ
  • 53. 参考文献 • JNI : Java Native Interfaceプログラミング 著者 ロブ・ゴードン 出版社 ピアソン • JDKドキュメント http://java.sun.com/j2se/1.4/ja/docs/ja/guide/jni/index.html
  • 54. おわり Ver.1.0 2002/08/22 Ver.1.1 2002/08/27