乡下人产国偷v产偷v自拍,国产午夜片在线观看,婷婷成人亚洲综合国产麻豆,久久综合给合久久狠狠狠9

  • <output id="e9wm2"></output>
    <s id="e9wm2"><nobr id="e9wm2"><ins id="e9wm2"></ins></nobr></s>

    • 分享

      JNI調(diào)用機(jī)制

       云端素館 2015-05-08
       JNI的簡(jiǎn)單介紹

      Java Native Interface (JNI)是java本地調(diào)用接口,所謂的native就是調(diào)用c/c++的程序。
      java調(diào)用C語言的情況一般有三種:
      1. 調(diào)用驅(qū)動(dòng)。由于操作系統(tǒng)提供的驅(qū)動(dòng)一般都是C接口,Java語言并不具備操作這些驅(qū)動(dòng)的能力。
      2. 對(duì)于計(jì)算量比較大,處理數(shù)據(jù)比較多的模塊,java的效率沒有C高,所以希望用C去完成。
      3. 對(duì)于某些功能模塊,可能Java和C的效率差不多,但是C已經(jīng)寫好了,就不想用Java重寫了。
      從程序的角度來說,主要關(guān)注兩種情況:
      • java訪問C
      • C訪問java
      對(duì)于理解JNI的調(diào)用實(shí)現(xiàn),對(duì)于理解Android的源碼有幫助,因?yàn)锳ndroid系統(tǒng)中大量的使用了JIN。

      Java訪問C

          任何語言直接的交互都必須遵循一定的規(guī)則或者協(xié)議,只有這樣雙方才能理解各自的意圖。
      java中定義native函數(shù),對(duì)于native函數(shù)只需要聲明,具體實(shí)現(xiàn)由C去實(shí)現(xiàn)。也就是說,native函數(shù)的
      實(shí)現(xiàn)與聲明是分離的,java負(fù)責(zé)聲明,C負(fù)責(zé)實(shí)現(xiàn)。所以java在編譯是不會(huì)關(guān)心具體實(shí)現(xiàn),編譯時(shí)就不會(huì)出錯(cuò)。

          如何調(diào)用的呢?在調(diào)用之前java是不會(huì)關(guān)心是否已經(jīng)實(shí)現(xiàn),只有在調(diào)用native方法的時(shí)候,去找C生成的動(dòng)態(tài)庫,如果
      找不到動(dòng)態(tài)庫,那么native方法就會(huì)報(bào)錯(cuò)。

         java如何找到C的函數(shù)的呢?

          java的native函數(shù)和C中的函數(shù)存在一種映射關(guān)系,這個(gè)映射關(guān)系就是遵循的一種協(xié)議或者稱為規(guī)則。
          比如,F(xiàn)ramework中AssetManager類中聲明了:
          
          private native final void init()

          該方法在C中對(duì)應(yīng)的是:
         static void android_content_AssetManager_init(JNIEnv* env, jobject clazz)

         從上面的對(duì)應(yīng)關(guān)系可以看出,在C中的規(guī)則就是,包名+類名+方法名,并且中間用下劃線分割
         第一個(gè)參數(shù)env,是JNIEnv對(duì)象,該對(duì)象代表一個(gè)Java虛擬機(jī)所運(yùn)行的環(huán)境,通過它可以訪問JVM內(nèi)部的各種對(duì)象;
          第二個(gè)參數(shù)jobject和是調(diào)用該函數(shù)的對(duì)象,上面的例子指的就是AssetManager對(duì)象;每個(gè)這樣的C函數(shù)的參數(shù)至少
          有這兩個(gè)參數(shù),如果native函數(shù)里有多個(gè)參數(shù),依次在后面排列,java的數(shù)據(jù)類型和JNI中的數(shù)據(jù)類型對(duì)應(yīng)關(guān)系,
      自己可以去網(wǎng)上查詢一下。

         當(dāng)java調(diào)用native函數(shù)時(shí),編譯器會(huì)向native引擎?zhèn)鬟f調(diào)用者的包名,函數(shù)名及參數(shù)類型,native引擎
      根據(jù)這些信息決定應(yīng)該調(diào)用具體的的哪個(gè)函數(shù)。

      在android中,native引擎中的AndroidRuntime類提供了一個(gè)registerNativeMethods()函數(shù),通過此函數(shù)
      定義java方法和C函數(shù)的映射關(guān)系。

      生成 .h文件

      java 的native方法和JNI中的c中的函數(shù)的對(duì)應(yīng)的定義文件頭文件(.h文件)可以手工寫,有些麻煩
      并且還容易出錯(cuò),java提供了一個(gè)javah工具,通過該工具可以從一個(gè)java文件自動(dòng)生成相應(yīng)的
      投文件,網(wǎng)上查詢一下具體用法。
          
      接下來就是根據(jù)頭文件去實(shí)現(xiàn)相應(yīng)的C代碼,然后生成動(dòng)態(tài)庫。

      如果想在java中調(diào)用native方法,需要使用在調(diào)用的代碼前面使用System.loadLibrary("lib_name")
      裝載該動(dòng)態(tài)庫。


      C訪問java

        雖然C訪問java的情況不多見,不過也是能遇到的。

       由于java中的函數(shù)在native引擎中并沒有直接的函數(shù)指針,java函數(shù)只能由java引擎去執(zhí)行,而不是C。所以訪問
      java不能通過指針,只能通過參數(shù)接口。

       java訪問c的時(shí)候,把類名,函數(shù)名,參數(shù)類型傳遞給native引擎,然后由native引擎處理C函數(shù),同理,
      C調(diào)用java時(shí),也需要把想要訪問的類名、函數(shù)名、參數(shù)傳遞給java引擎。

      按照如下步驟:

      1. 獲取java對(duì)象的類
        jclass cls = env->GetObjectclass(jobject);
        jobject就是需要調(diào)用的誰的方法,java對(duì)象在JNI中的表示。
      2. 獲得java方法的Id值
        jmethodId mid = env->GetMethodId(cls, "method_name", "([Ljava/lang/String;)V");
        第一個(gè)參數(shù)是java對(duì)象對(duì)應(yīng)的類
        第二個(gè)參數(shù)是java中的方法名稱
        第三個(gè)參數(shù)是數(shù)據(jù)類型和返回值
        解釋一下第三個(gè)參數(shù):
        參數(shù)在括弧中,返回值在括弧外, ([Ljava/lang/String;)V" : [Ljava/lang/String代表參數(shù)類型,如果是類包名用
        “/”分開,并且前面加上又給大寫的L。
        java和native數(shù)據(jù)類型對(duì)應(yīng)表
        java類型 native類型
        boolean Z
        byte B
        char C
        double D
        float F
        int I
        long L
        Object 'L' + '包名'+';'
        short S
        這個(gè)參數(shù)可以自己手工寫,還是那樣容易出錯(cuò),java提供了一個(gè)工具用來查看參數(shù)簽名,使用javap工具可以自動(dòng)生成,自己從網(wǎng)上查詢一下即可。
      3. 調(diào)用函數(shù)
        env->CallXXXMethod(jobject, mid, ret);

        其中XXX是不同的類型,包括:Void,Oject,Boolean,Byte,Char,Short,Int,Long,Float,Double
        第一個(gè)參數(shù)是調(diào)用的類的對(duì)象
        第二個(gè)參數(shù)是上一步獲得的方法的id
        第三個(gè)參數(shù)數(shù)是返回值
      上面是調(diào)用方法,調(diào)用java的變量也類似:

      1. 獲取java對(duì)象的類
        jclass cls = env->GetObjectclass(jobject);
      2. 獲得變量的id
        jfiledId fid = env->GetFiledId(cls, "fileName", "I");
      3. 獲取變量值
        value = env->GetXXXField(env, jobject, fid);

      在C中使用持久對(duì)象和保持持久對(duì)象

       C中本身無法保存持久對(duì)象,把持久對(duì)象保存到一個(gè)int類型的變量上,使用的時(shí)候再強(qiáng)制轉(zhuǎn)型成對(duì)象。

        本站是提供個(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)論公約

        類似文章 更多