久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

JNI全攻略之三--JNI頭文件分析

 點(diǎn)點(diǎn)滴滴 2011-12-12

JNI全攻略之三--JNI頭文件分析  

2006-12-11 11:21:52|  分類: JNI |字號(hào) 訂閱

JNI頭文件分析

       為了分析JNI頭文件,特意寫了HeaderTest這個(gè)包含多個(gè)不同的native方法的測(cè)試類,。

江蘇 無錫 繆小東

1.    測(cè)試文件HeaderTest.java

       這是一個(gè)相當(dāng)簡單的文件。前兩個(gè)為成員變量,、第三個(gè)為非本地方法,,主要考察成員變量和非本地方法,是否在頭文件中出現(xiàn)。后面一段是幾種類型的本地方法,,例如無輸入無輸出的本地方法,、輸入輸出基本數(shù)據(jù)類型的本地方法、輸入輸出String類型的本地方法,、輸入輸出java自定義的對(duì)象的本地方法,、輸出java自定義的接口的本地方法、輸出自定義的對(duì)象的本地方法,。后面的就是這幾種類型對(duì)應(yīng)的輸入輸出為數(shù)組的方法,。最后總和的方法。在此類的外部有一個(gè)自定義的輔助類Student,。本例中還考察private,、friendlypublic等訪問權(quán)限對(duì)本地方法產(chǎn)生頭文件的影響,。以及方法重載對(duì)頭文件中相應(yīng)方法的影響……太羅嗦了,!大家就看看下面的java文件吧!??!

import java.util.*;

public class HeaderTest{

       private int i = 0 ;

       float f = 0f;

       public void XXX(String s){

              ;

       }     

 

       private native void  doVoid();

       native int doShort();

       native void doArray(Object[] o );

       native int doInt(int i);      //byte ,short ,int,long,float,double ,boolean,char      

       native int doInt(double d);    //byte ,short ,int,long,float,double ,boolean,char

       native int doInt(Object o);    

       native int doInt(double d1,double d2);

       static native int doInt(double d1 ,double d2,double d3);

       static native int doInt(double d1 ,float f,boolean b ,char[] c );  

      

       native int doInt(int[] i);

       native int doInt(int[] i1,double[] i2 );    

       static native int doInt(int[] i1,double[] i2 ,Object[] o );

      

       public native String doString(String s);

       public native Object doObject(Object o );

       public native Enumeration doInterface(Iterator it);

       public native Student doStudent(Student s);

      

 

//     native int[] doInt(int[] i);  //byte ,short ,int,long,float,double ,boolean,char

       public native String[] doString(String[] s);

       public native Object[] doObjects(Object[] o );

       public native Enumeration[] doInterface(Iterator[] it);

       public native Student[] doStudent(Student[] s);

             

       public native static Object doAll(int[] i , String[] s , Student[] student );                       

}

 

class Student{}

二、頭文件HeaderTest.h

       編譯上面的文件,,然后對(duì)編譯后的類文件,,使用javah命令,產(chǎn)生HeaderTest.h頭文件,。下面就是該頭文件的一部分,。

 

1.        

2.         #include <jni.h>

3.        

4.         #ifndef _Included_HeaderTest

5.         #define _Included_HeaderTest

6.         #ifdef __cplusplus

7.         extern "C" {

8.         #endif

 

9.        

14.     JNIEXPORT void JNICALL Java_HeaderTest_doVoid (JNIEnv *, jobject);

……

 

1.         #ifdef __cplusplus

2.         }

3.         #endif

4.         #endif

 

       為了閱讀的方便,給此頭文件加了行號(hào),!

三,、JNI頭文件的組成

       JNI頭文件一般由三部分組成:1.頭文件;2.本地方法的注冊(cè),;3.本地方法在頭文件中的表示,。

1.        1-8 CC++的頭,,它包含了我們?cè)?/span>VC工具中要使用的jni.h的頭文件,,以及其它的一些指令。(相信你對(duì)C,、C++比較了解吧,!不了解可以閱讀相關(guān)書籍!我這里就不講解了)

2.        以后的每隔6行就是一個(gè)本地方法對(duì)應(yīng)的頭文件中的方法,。這些方法的注釋部分包含Class,、Method,、和Signature三部分。Class當(dāng)然就是具有此本地方法的類的名稱了,,在我們的例子中為HeaderTest,;Method就是本地方法的名稱了,我們例子中有如doStudent的方法,;Signature是方法的標(biāo)識(shí),,它是一個(gè)標(biāo)識(shí)符,主要供我們?cè)?/span>JNI操作java對(duì)象的方法使用的,。本節(jié)只簡單講述其特征,,具體使用見本博客的后續(xù)文章。

3.        接著就是一個(gè)本地方法在頭文件中的表示了,!例如:

              JNIEXPORT jobject JNICALL Java_HeaderTest_doObject (JNIEnv *, jobject, jobject);

 

四,、分析

1.方法組成分析

       從上面的頭文件可以看出:頭文件包含以下7個(gè)部分:

       JNIEXPORT <JNIType> JNICALL Java_HeaderTest_doVoid (JNIEnv *, jobject);

              1        2       3    4      5       6        7

       我就簡單地介紹這7個(gè)部分吧!

1)        JNIEXPORT1)和JNICALL3)都是JNI的關(guān)鍵字,,表示此函數(shù)是要被JNI調(diào)用的,。

2)        <JNIType>2)為本地方法返回的數(shù)據(jù)類型,對(duì)應(yīng)與java源文件中的該方法返回的數(shù)據(jù)類型

3)        Java4)為JNI中標(biāo)識(shí)此方法來源于java的標(biāo)識(shí)頭

4)        _HeaderTest5)表示該方法所在的類,。當(dāng)該類在包中時(shí)前面會(huì)按次序加上包名,。我將上面的類文件放入名為mxd的包中,相應(yīng)的5部分就為mxd_HeaderTest了,,其它類推吧,!

5)        _doVoid6)為JNI中對(duì)應(yīng)與java文件中本地方法的方法名。這不是完全對(duì)應(yīng)的哦,!重載方法是一個(gè)例外!

6)        (JNIEnv *, jobject)7)方法的最后一部分哦,!比較復(fù)雜,,它們有一個(gè)共同的特點(diǎn),包含JNIEnv *――它是一個(gè)接口指針,,用于定位函數(shù)表中的函數(shù),!在JNI規(guī)范中一般稱為“Interface Pointer”??吹竭@兒好像和過程調(diào)用很類似了,!是的,JNI中的操作過程,,就是面向過程的,!后面的jobject是一個(gè)指向該類的指針,類似與C語言中的this,。這個(gè)第二個(gè)參數(shù)是變化的,,當(dāng)該方法為類的實(shí)例方法時(shí)該參數(shù)為jobject,;當(dāng)該方法為類方法(即靜態(tài)方法)時(shí)該參數(shù)為jclass,指向該類的class,。詳細(xì)見下面,。

 

2.java的數(shù)據(jù)類型和JNI中數(shù)據(jù)類型的映射

       以下是HeaderTest.java的源文件中的本地方法和HeaderTest.h頭文件中的方法對(duì)照!

       private native void  doVoid();

       native int doInt(int i);      //byte ,short ,int,long,float,double ,boolean,char

       public native String doString(String s);

       public native Object doObject(Object o );

       public native Enumeration doInterface(Iterator it);

       public native Student doStudent(Student s);     

 

       native int[] doInt(int[] i);  //byte ,short ,int,long,float,double ,boolean,char

       public native String[] doString(String[] s);

       public native Object[] doObjects(Object[] o );

       public native Enumeration[] doInterface(Iterator[] it);

       public native Student[] doStudent(Student[] s);

 

JNIEXPORT void JNICALL Java_HeaderTest_doVoid (JNIEnv *, jobject);

JNIEXPORT jint JNICALL Java_HeaderTest_doInt__I (JNIEnv *, jobject, jint);

JNIEXPORT jstring JNICALL Java_HeaderTest_doString__Ljava_lang_String_2 (JNIEnv *, jobject, jstring);

JNIEXPORT jobject JNICALL Java_HeaderTest_doObject (JNIEnv *, jobject, jobject);

JNIEXPORT jobject JNICALL Java_HeaderTest_doInterface__Ljava_util_Iterator_2 (JNIEnv *, jobject, jobject);

JNIEXPORT jobject JNICALL Java_HeaderTest_doStudent__LStudent_2 (JNIEnv *, jobject, jobject);

JNIEXPORT jintArray JNICALL Java_HeaderTest_doInt___3I (JNIEnv *, jobject, jintArray);

JNIEXPORT jobjectArray JNICALL Java_HeaderTest_doString___3Ljava_lang_String_2 (JNIEnv *, jobject, jobjectArray);

JNIEXPORT jobjectArray JNICALL Java_HeaderTest_doObjects (JNIEnv *, jobject, jobjectArray);

JNIEXPORT jobjectArray JNICALL Java_HeaderTest_doInterface___3Ljava_util_Iterator_2(JNIEnv *, jobject, jobjectArray);

JNIEXPORT jobjectArray JNICALL Java_HeaderTest_doStudent___3LStudent_2 (JNIEnv *, jobject, jobjectArray);

JNIEXPORT jobject JNICALL Java_HeaderTest_doAll (JNIEnv *, jclass, jintArray, jobjectArray, jobjectArray);

 

       從上面的對(duì)比可以看到:

1)        java中的返回值voidJNI中的void是完全對(duì)應(yīng)的哦?。▋H僅一個(gè)而已),。

2)        java中的基本數(shù)據(jù)類型(byte ,short ,int,long,float,double ,boolean,char8種)在JNI中對(duì)應(yīng)的數(shù)據(jù)類型只要在前面加上j就對(duì)應(yīng)了(jbyte ,jshort ,jint,jlong,jfloat,jdouble ,jboolean,jchar)。

3)        java中的對(duì)象,,包括類庫中定義的類,、接口以及自定義的類接口,都對(duì)應(yīng)于JNI中的jobject,。

4)        java中基本數(shù)據(jù)類型的數(shù)組對(duì)應(yīng)與JNI中的j<type>array類型,。(type就是上面說的8種基本數(shù)據(jù)類型)

5)        java中對(duì)象的數(shù)組對(duì)應(yīng)于JNI中的jobjectArray類型。(在java中一切對(duì)象,、接口以及數(shù)組都是對(duì)象)

 

       下圖是JNI規(guī)范中java數(shù)據(jù)類型和JNI數(shù)據(jù)類型的映射圖,。

       第一幅為基本數(shù)據(jù)類型的映射圖:

 

 

       第二幅為引用數(shù)據(jù)類型的映射圖:

 

3.重載方法的區(qū)別

       以下是幾個(gè)沒有重載的方法及其在JNI頭文件中對(duì)應(yīng)的方法:

       private native void  doVoid();

       native int doShort();

       native void doArray(Object[] o );

 

JNIEXPORT void JNICALL Java_HeaderTest_doVoid (JNIEnv *, jobject);

JNIEXPORT jint JNICALL Java_HeaderTest_doShort (JNIEnv *, jobject);

JNIEXPORT void JNICALL Java_HeaderTest_doArray (JNIEnv *, jobject, jobjectArray);

       從上面的例子可以看出:沒有重載的方法在JNI的頭文件中對(duì)應(yīng)的方法和java中本地方法的名稱是一致的。

 

 

       以下是幾個(gè)簡單的重載方法:

       native int doInt(int i);      //byte ,short ,int,long,float,double ,boolean,char      

       native int doInt(double d);    //byte ,short ,int,long,float,double ,boolean,char

       native int doInt(double d1,double d2);

       static native int doInt(double d1 ,double d2,double d3);

       static native int doInt(double d1 ,float f,boolean b ,char[] c );

       native int doInt(Object o);    

 

JNIEXPORT jint JNICALL Java_HeaderTest_doInt__I (JNIEnv *, jobject, jint);

JNIEXPORT jint JNICALL Java_HeaderTest_doInt__D (JNIEnv *, jobject, jdouble);

JNIEXPORT jint JNICALL Java_HeaderTest_doInt__DD(JNIEnv *, jobject, jdouble, jdouble);

JNIEXPORT jint JNICALL Java_HeaderTest_doInt__DDD (JNIEnv *, jclass, jdouble, jdouble, jdouble);

JNIEXPORT jint JNICALL Java_HeaderTest_doInt__DFZ_3C (JNIEnv *, jclass, jdouble, jfloat, jboolean, jcharArray);

JNIEXPORT jint JNICALL Java_HeaderTest_doInt__Ljava_lang_Object_2 (JNIEnv *, jobject, jobject);

       從上面的對(duì)比可以看出:重載方法時(shí),,方法的后面還有一個(gè)表示方法參數(shù)的“后綴”,。例如上面操作的變量為Int時(shí)加一個(gè)表示此類型的標(biāo)識(shí)“I”;多個(gè)類型當(dāng)然依次加多個(gè)了,;當(dāng)某個(gè)變量為數(shù)組時(shí)在其類型前面會(huì)加一個(gè)“3,;當(dāng)其為對(duì)象時(shí)后面會(huì)加一個(gè)“L”表示這是一個(gè)對(duì)象,以及一個(gè)該對(duì)象的路徑,,不過路徑之間用“_”代替包路徑的“.”或者文件路徑的“/”哦,!這對(duì)應(yīng)于Signature。見后面,!

 

 

       下面是復(fù)雜的例子:

       public native Student[] doStudent(Student[] s1);

       public native Student[] doStudent(Student[] s1,Student[] s2);

 

JNIEXPORT jobjectArray JNICALL Java_HeaderTest_doStudent___3LStudent_2 (JNIEnv *, jobject, jobjectArray);

JNIEXPORT jobjectArray JNICALL Java_HeaderTest_doStudent___3LStudent_2_3LStudent_2(JNIEnv *, jobject, jobjectArray, jobjectArray);

       從上面的例子可以看出,,方法重載時(shí),方法后要依次加上參數(shù)名稱,,前面知道了數(shù)組要在參數(shù)類型前加“3,,從上面的例子看出:參數(shù)為對(duì)象時(shí)對(duì)象名稱后還要加上“2,表示該參數(shù)為一個(gè)對(duì)象,。

 

4.實(shí)例方法和靜態(tài)方法的區(qū)別

       以下是本地實(shí)例方法和本地類方法的比較,。紅色的為java中的本地方法,藍(lán)色的為JNI頭文件中對(duì)應(yīng)的方法,。

       public native Student[] doStudent(Student[] s);

       public native static Object doAll(int[] i , String[] s , Student[] student );

 

JNIEXPORT jobjectArray JNICALL Java_HeaderTest_doStudent___3LStudent_2 (JNIEnv *, jobject, jobjectArray);

JNIEXPORT jobject JNICALL Java_HeaderTest_doAll (JNIEnv *, jclass, jintArray, jobjectArray, jobjectArray);

       從上面的比較可以看出:

       在本地實(shí)例方法中該參數(shù)為jobject,,代表對(duì)象本身,在本地靜態(tài)方法中該參數(shù)為jclass,。這是它們的區(qū)別,。關(guān)于如何操作代表該實(shí)例的jobject和操作該類的jclass請(qǐng)關(guān)注后續(xù)文章,。

 

 

 

5.Signature

       JNI頭文件中提到Signature,它主要用于操作Java類中的方法,。Signature一般由兩部分組成:1.方法參數(shù),;2.方法返回值。

1.        方法參數(shù)包含在一個(gè)括號(hào)中,,返回值在括號(hào)外,!

2.        方法參數(shù)個(gè)數(shù)較多時(shí)會(huì)依次以“;”隔開。

3.        當(dāng)參數(shù)或者返回值是基本數(shù)據(jù)類型時(shí),,必須用其在JNI中的描述符表示,。下表就是Java基本數(shù)據(jù)類型對(duì)應(yīng)的JNI中的描述符。

4.        方法參數(shù)或者返回值為java中的對(duì)象時(shí),,必須以“L”加上其路徑,,不過此路徑必須以“/”分開,自定義的對(duì)象也使用本規(guī)則,,不在包中時(shí)直接“L”加上類名稱,。

5.        當(dāng)參數(shù)或者返回值為數(shù)組時(shí),前面必須加上“[”,!

 

       以上就是Signature表示方法的規(guī)則哦,!看看下面一些Signature能一個(gè)個(gè)轉(zhuǎn)換為相應(yīng)的方法嗎?

([LStudent;)[LStudent;

([I[Ljava/lang/String;[LStudent;)Ljava/lang/Object;

([LStudent;[LStudent;)[LStudent;

([Ljava/util/Iterator;)[Ljava/util/Enumeration;

([Ljava/lang/Object;)[Ljava/lang/Object;

([Ljava/lang/String;)[Ljava/lang/String;

(LStudent;)LStudent;

       能明白就好了,!后續(xù)的使用JNI操作Java對(duì)象你可以入門了哦?。?/span>

6.其它

1.        類中的成員變量,、非本地方法在JNI中是不會(huì)出現(xiàn)的,。即javah產(chǎn)生頭文件時(shí)只會(huì)關(guān)心本地方法。

2.        private,、friendly,、protected以及public這些方法限制符不會(huì)在JNI的頭文件中出現(xiàn)。這些訪問修飾符只有在其它類使用這些方法時(shí)有效,!JNI中不關(guān)心此修飾符!

3.        當(dāng)我們給HeaderTest.java指定一個(gè)包時(shí),,不僅頭文件中的方法的前面加了包名,,并且產(chǎn)生的頭文件也變?yōu)?/span>mxd_HeaderTest.h

 

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,,所有內(nèi)容均由用戶發(fā)布,,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式,、誘導(dǎo)購買等信息,,謹(jǐn)防詐騙,。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào),。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多