All articles in jni

メソッドを呼び出す

ネイティブコードからクラスやオブジェクトのメソッドを呼び出す.流れサンプルインスタンスメソッドとスタティックメソッドメソッドIDの取得とシグネチャjavap 流れ メソッドを呼び出す時の流れは,フィールドの取得や設定とそんなに変わらない.以下にその流れを示す. インスタンスメソッドの場合 スタティックメソッドの場合 必要があればGetObjectClassでjclassを取得する GetMethodIDでメソッドIDを取得 GetStaticMethodIDでメソッドIDを取得 Call<Type>Methodでメソッドを呼び出す CallStatic<Type>Methodでメソッドを呼び出す <Type>にはメソッドの返り値の型と対応するInt,Short,Byteなどが入る. サンプル 流れが掴めたところでサンプルを示す.まずはネイティブコードから呼び出されるメソッドを保持するクラス. ここにはスタティックメソッドとインスタンスメソッド,そしていろんなアクセス修飾子を混ぜてみた.次にこのクラスのメソッドをネイティブコードを介して呼び出すクラス. そしてネイティブメソッド.まずヘッダ. そして本体. 以下実行結果.publicVoidMethod()pkgPrivateIntMethod()return 1protectedCharMethod(hoge)return hprivateDoubleMethod(1.0)return 1.0フィールドの場合と同様,privateなメソッドを呼び出したりもできる. … More メソッドを呼び出す

参照

参照とポインタは同じ概念のはずだが,JNIでは明確に区別する必要がある.JavaにはポインタがないJNIで何を考慮すべきかローカル参照グローバル参照参照についてのまとめ Javaにはポインタがない 「JavaにはポインタがないからCより簡単だ」これはJavaの入門書などでよくみかける.確かにJavaにはポインタと呼ばれるものはないが,参照があるので同じことだ.まともなプログラミング言語ならポインタに相当するものは大抵あるものだ.ないとなるとその言語の表現力に大きく影響してしまう.で,Cにおけるポインタとは何か.「オブジェクトを指し示すもの」である.多くの場合それはアドレスで実装されるが,別にC言語の仕様ではない(ハズ)が,ここではアドレスで実装するものと考える.Javaにおける参照とは何か.これもやはり「オブジェクトを指し示すもの」である.実装についての仕様はよくわからないが,以下を踏まえておく必要がある.JVMはGCでオブジェクトを削除する.JVMはGCでオブジェクトを再配置する.オブジェクトのアドレスがJVMによって動的に変化するから,参照は直接,または短絡的にアドレスで実装しいるわけではないと思う.オブジェクトへの参照と実際のアドレスはJVMによって管理される.ポインタと参照にはこのような違いがあるが,ポインタと参照は同じ「オブジェクトを指し示すもの」であるので,プログラマから見ればC,Javaそれぞれ単独でコーディングする上では両者の違いはほとんどない(「ポインタ演算」相当の「参照演算」なんてものはないが).が,JNIで両者が出会うとき,ポインタと参照の違いは明確に意識しておく必要がある. JNIで何を考慮すべきか ポインタと参照の違いは簡単に言うと,「プログラマが責任をもって管理するか,JVMがいろいろと操作をするか」である.そしてこの違いはCとJavaが出会うJNIのネイティブコードでは特に意識する必要がある.ネイティブコードはCもしくはC++である.いうまでもなく,ポインタは従来どおりのポインタとして扱える.問題は参照である.概念的にはポインタと参照は同じだが,参照はJVMにより管理,操作される.したがって,たとえ参照がポインタと同じように見えてもプログラマが好き勝手に保持,操作してはいけない. ローカル参照 JVMはネイティブコードに渡した参照に関する情報をテーブルに保持する.これにより,JVMは「ネイティブコードでこの参照が使用されているからGCのときに注意しなければならない(削除や移動をしてはいけない)」ことがわかる.このテーブルに保持される参照にはネイティブメソッドの引数にある全ての参照と返り値のための参照が含まれる.このテーブルに含まれる参照はローカル参照と呼ばれる.ローカル参照はそのネイティブメソッドの呼び出しの間でだけ有効である.すなわちネイティブコードのグローバル変数で参照を保持しておいて,複数のネイティブメソッドで使用することはできない.ネイティブメソッドの呼び出しが異なれば,テーブルに保持されている参照は無効になる.したがって,別のネイティブメソッドでその参照を使用すると結果は保証されない.やってはいけない例を以下に示す.まず不正なネイティブメソッドを呼び出すJavaクラス. 上のクラスファイルから生成されるヘッダ. そして不正なネイティブコード. 上のネイティブコードでは,methodAでオブジェクトへの参照である引数objをグローバル変数invalidLocalReferenceに格納してmethodBでそれを使用している.これを実行すると私の環境では以下のようになった. なんかアボートした.黙ってそのまま実行されるよりはましだ. グローバル参照 先のサンプルは,ネイティブコードにおいてローカル参照をグローバル変数に格納する間違った例であった.しかし,JNIでは参照をネイティブコードでグローバル変数に格納する手段を提供されている.このとき,その参照はグローバル参照と呼ばれる.具体的な方法は,JVMにあるローカル参照をネイティブコードにおいてグローバルに参照する(グローバル参照とする)ことを伝えるものである.それはJNIEnvの関数であり,jni.hでは以下のように定義されている.jobject (JNICALL *NewGlobalRef)(JNIEnv *env, jobject lobj);引数にlobjとあるのはローカル参照ということだろう.そして返り値をグローバル参照としてグローバル変数に格納すればよい.この関数を使用して先の間違ったサンプルを修正してみた.まず,グローバル参照を使用するネイティブコードを呼び出すJavaコード. そして上のJavaコードから生成されるヘッダ. そしてグローバル参照を使用するネイティブコード.

フィールドの取得

ネイティブコードからクラスやオブジェクトのフィールドを取得する.サンプルインスタンスネイティブメソッドとスタティックネイティブメソッドの違いJNIEnvjobjectからjclassを取得するフィールドIDの取得フィールド値の取得まとめ サンプル 説明は後にしていきなりサンプルを示す.特にネイティブコードの最初の関数で雰囲気を掴めると思う.まず問題のフィールドを保持しているクラス. そしてネイティブコード. 以上を以下のクラスから呼び出す. インスタンスネイティブメソッドとスタティックネイティブメソッドの違い JNIEnv すべてのネイティブメソッドの第一引数はJNIEnv *である.JNIEnv *は関数ポインタを差しているポインタへのポインタである.関数ポインタが差している関数がネイティブメソッドとJavaVM環境との橋渡しとなる関数郡である.これらの関数を使用することで,ネイティブメソッドから簡単にオブジェクトのフィールドを取得,設定したりメソッドを呼び出したりできる. jobjectからjclassを取得する フィールドIDの取得 型 シグネチャ byte B char C double D … More フィールドの取得

JNI

ろくにCをやってないのにJava Native Interfaceをちょっとやってみた.基本編クラスやオブジェクトの取扱 基本編JNIの基本とりあえずHello2003-07-20T15:13+09:00 matsuJavaからhelloを出力するネイティブコードを呼んでみる.nativeメソッドの引数(プリミティブ型)2003-07-20T15:13+09:00 matsunativeメソッドから引数を渡せなければ,あんまり嬉しくない.なので,ここではいろんなプリミティブ型の引数を渡しみる.フィールドの取得2003-07-20T15:13+09:00 matsuネイティブコードからクラスやオブジェクトのフィールドを取得する.フィールドの設定2003-07-20T15:13+09:00 matsuネイティブコードからクラスやオブジェクトのフィールドを設定する.メソッドを呼び出す2003-07-20T15:13+09:00 matsuネイティブコードからクラスやオブジェクトのメソッドを呼び出す.クラスやオブジェクトの取扱ネイティブコードでもクラスやオブジェクトを取扱うことができる.参照2003-07-20T15:13+09:00 matsu参照とポインタは同じ概念のはずだが,JNIでは明確に区別する必要がある.オブジェクトの生成2003-07-20T15:13+09:00 matsuネイティブコードでもnewに相当することができる.TOPページ不安火FeatureAutomakeAXISBASHスクリプトCommon LispC++C言語GDBGTKHibernateJFreeChartJNIMPEGNMSPerlPostgreSQLRestletSpringStrutsTaglibXMLXUL埋火PC Clusterベンチマーク調査ギガビットイーサネットの調査MPIで並列プログラミングSoftwarehpl_filterSiteGeneratorGCMonHKBSoftware(En)SiteGenerator