1. 程式人生 > >jni應用(如何訪問方法Java的類)

jni應用(如何訪問方法Java的類)

本文將通過例項來說明如何在jni 訪問Java的類和成員。開始先介紹所有物件分類的方法,最後才是例項說明。

訪問物件的屬性和方法

1、例項屬性的訪問

  jfieldID  GetFieldID (JNIEnv*env, jclass clazz, const char *name, const char*sig);                

功能:返回類的例項(非靜態)域的屬性 ID。該域由其名稱及簽名指定。訪問器函式的Get<type>Field Set<type>Field

系列使用域 ID檢索物件域。GetFieldID()不能用於獲取陣列的長度域。應使用

GetArrayLength()

引數  envJNI介面指標。

               clazzJava類物件。

              name:該屬性的Name名稱

               sig該屬性的域簽名。

返回值:屬性ID。如果操作失敗,則返回NULL

丟擲 NoSuchFieldError:如果找不到指定的域。

             ExceptionInInitializerError:如果由於異常而導致類初始化程式失敗。

             OutOfMemoryError:如果系統記憶體不足。

   Get<type>Field

例程

  NativeType  Get<type>Field (JNIEnv*env, jobject obj, jfieldIDfieldID);                

功能:該訪問器例程系列返回物件的例項(非靜態)域的值。要訪問的域由通過呼叫GetFieldID()而得到的域 ID 指定。

引數   envJNI介面指標。

                objJava物件(不能為 NULL)。

                fieldID:有效的域 ID

返回值屬性的內容。

  Get<type>Field例程名本地型別

              GetObjectField()                 jobject     

               GetBooleanField()              jboolean  

              GetByteField()                    jbyte        

              GetCharField()                    jchar        

              GetShortField()                   jshort       

              GetIntField()                       jint  

              GetLongField()                    jlong         

              GetFloatField()                   jfloat        

               GetDoubleField()     jdouble    

   Set<type>Field 方法族

  void  Set<type>Field (JNIEnv *env, jobject obj, jfieldIDfieldID,  NativeTypevalue);           

功能該訪問器例程系列設定物件的例項(非靜態)屬性的值。要訪問的屬性由通過呼叫SetFieldID()而得到的屬性 ID指定。

引數  envJNI介面指標。

              objJava物件(不能為 NULL)。

             fieldID:有效的域 ID

              value:域的新值。

方法族如下:

   Set<type>Field 方法族本地型別

                 SetObjectField()                   jobject     

                 SetBooleanField()                 jboolean  

                  SetByteField()                      jbyte        

                 SetCharField()                      jchar        

                 SetShortField()                    jshort       

                 SetIntField()                        jint  

                  SetLongField()                     jlong         

                 SetFloatField()                     jfloat        

                 SetDoubleField()                 jdouble    

 2、靜態屬性的訪問 :也存在相同的方法,

jfieldID  GetStaticFieldID (JNIEnv *env,jclass clazz, const char *name, const char*sig);  

       NativeType GetStatic<type>Field (JNIEnv*env,jclass classzz , jfieldIDfieldID);           

voidSetStatic<type>Field (JNIEnv *env,jclassclasszz, jfieldIDfieldID,  NativeTypevalue);           

它們與例項屬性的唯一區別在於第二個引數jclass classzz代表的是類引用,而不是類例項。

 3、呼叫例項方法

  jmethodID GetMethodID(JNIEnv *env, jclass clazz,    const char*name, const char *sig);               

功能:返回類或介面例項(非靜態)方法的方法 ID。方法可在某個 clazz 的超類中定義,也可從 clazz繼承。該方法由其名稱

和簽名決定。 GetMethodID()可使未初始化的類初始化。要獲得建構函式的方法 ID,應將 <init>作為方法名,同時將

        void (V)作為返回型別。

引數  envJNI介面指標。

               clazzJava類物件。

               name:方法名。

               sig:方法的簽名。

返回值方法 ID,如果找不到指定的方法,則為 NULL

丟擲    NoSuchMethodError:如果找不到指定方法。

                 ExceptionInInitializerError:如果由於異常而導致類初始化程式失敗。

                 OutOfMemoryError:如果系統記憶體不足。

 Call<type>Method例程Call<type>MethodA例程Call<type>MethodV例程

 NativeType Call<type>Method (JNIEnv*en v,  jobject obj , jmethodIDmethodID, ...);     //引數附加在函式後面,              

 NativeType Call<type>MethodA (JNIEnv *env, jobject obj, jmethodID methodID,jvalue *args);  //引數以指標形式附加

  NativeType Call<type>MethodV (JNIEnv *env, jobject obj,jmethodID methodID, va_listargs); //引數以"連結串列"形式附加

說明:這三個操作的方法用於從本地方法呼叫Java例項方法。它們的差別僅在於向其所呼叫的方法傳遞引數時所用的機制。

這三個操作將根據所指定的方法 ID呼叫 Java 物件的例項(非靜態)方法。引數 methodID必須通過呼叫 GetMethodID() 

來獲得。當這些函式用於呼叫私有方法和建構函式時,方法 ID必須從obj 的真實類派生而來,而不應從其某個超類派生。

當然,附加引數可以為空

引數  envJNI介面指標。

            objJava物件。

            methodID:方法 ID

返回值返回呼叫 Java方法的結果。

丟擲執行 Java方法時丟擲的異常。

下表根據結果型別說明了各個方法型別。使用者應將Call<type>Method中的 type 替換為所呼叫方法的Java 型別(或使用表

中的實際方法名),同時將 NativeType替換為該方法相應的本地型別。省略掉了其他兩種型別。

Java層返回值方法族本地返回型別NativeType

返回值為voidCallVoidMethod()   A / V        ()

返回值為引用型別:     CallObjectMethod( )                            jobect

返回值為boolean    CallBooleanMethod ( )                         jboolean

返回值為byte          CallByteMethod( )                                jbyte

返回值char           CallCharMethod( )                               jchar

返回值short          CallShortMethod()                              jshort       

返回值為int            CallIntMethod()                                     jint  

返回值為long    CallLongMethod()                             jlong        

返回值為float   CallFloatMethod()                                 jfloat        

返回值為double    CallDoubleMethod()                          jdouble    

 4、呼叫靜態方法:也存在如下方法群,

jfieldID  GetStaticMethodID (JNIEnv *env,jclass clazz, const char *name, const char*sig);  

       NativeType Call<type>Method (JNIEnv*env,jclass classzz , jfieldIDfieldID);      

例項如下:

Java 的類如下:

/***test class 需要測試的jni裡訪問的類********/

public class testTime{

  public int mVersion;

  private int year;
  private int month;
  private int day;
  private int hour;
  private int minute;
  private int second;
  private int reserved;

  public
    byte[] channelCdata = new byte[1024];

public testTime()

{

}

  public
    void setTdtDate(int mYear, int mMonth, int mDay)
    {
    this.year = mYear;
    this.month = mMonth;
    this.day = mDay;
    }
  public
    void setTdtTime(int mHour, int mMinute, int mSecond)
    {
    this.hour = mHour;
    this.minute = mMinute;
    this.second = mSecond;
    }

  public
    void SetCharArray(byte[] cData, int data_size)
    {
    if (data_size == 0) {
        return;
    }
    byte[] buffer = new byte[data_size];
    System.arraycopy(cData, 0, buffer, 0, data_size);
    String charText= new String(buffer);
    }

 public
    byte[] getCharArray()
    {
          String myNane = "gchen"
          byte[] charArray = myNane.getBytes();
          return charArray;
    }

}

/***************jni java class***********************/

package android.com.test;

public class jniTest{

   public
    native final int jni2JavaClass(Object objTestTime);

static
    {
        Log.i(TAG, "load testjni lib");
        System.loadLibrary("testjni");
    }

public jniTest()

{

}

public testJniCallJava()

{

 testTime mtim = newtestTime();

  jni2JavaClass((Object)mtim);

}

}

/***************jni cpp***********************/

static const char *classPathName = "android/com/test/jniTest";

static JNINativeMethod methods[] = {
    { "jni2JavaClass", "(Ljava/lang/Object;)I", (void *)android_com_test_jniTest_jni2JavaClass},
};

int android_com_test_jniTest_jni2JavaClassJNIEnv *env, jobject thiz,jobjectobjTestTime)

{

int ret = -1;

 jclass testTime= env->GetObjectClass(objTestTime);  /********獲取Java的類引用*********/
  if (testTime== NULL) {
              return ret;
       }

jfieldID mfield = env->GetFieldID(testTime, "mVersion", "I");/**********獲取Java的成員以及型別**************/

int version = env->GetIntField(objTestTime,mfield);/**********訪問Java的成員,讀取**************/

env->SetIntField(objTestTime,(jin)0x00) ;;/**********訪問Java的成員,設定**************/

jmethodID mMethodld == env->GetMethodID(testTime, "setTdtDate", "(III)V");  /**********獲取Java的方法以及型別**************/
env->CallVoidMethod(objTestTime,mMethodld, 2016, 01,01); /**********呼叫Java的方法**************/

mMethodld== env->GetMethodID(testTime, "setTdtTime", "(III)V");
env->CallVoidMethod(objTestTime,mMethodld, 9, 30,30);

 char mycontry[20] = "China"

 jbyteArray byteArray;
 jint cDataSize = strlen(mycontry);

 byteArray = env->NewByteArray(cDataSize);
 env->SetByteArrayRegion(byteArray, (jsize)0, (jsize)cDataSize, (jbyte *)mycontry);
 mMethodld = env->GetMethodID(testTime, "SetCharArray", "([BI)V");/**********獲取Java的方法以及型別**************/
 env->CallVoidMethod(objTestTime, mMethodld,byteArray, cDataSize);  /**********訪問Java的方法**************/
 env->DeleteLocalRef(byteArray);

  char myname[20] = "";

 mMethodld = env->GetMethodID(testTime, "getCharArray", "()[B"); /**********獲取Java的方法以及型別**************/
 byteArray = (jbyteArray)env->CallObjectMethod(objTestTime, mMethodld);/**********訪問Java的方法**************/
 jsize arrayLen = env->GetArrayLength(byteArray);
if (arrayLen > 0) {
        env->GetByteArrayRegion(byteArray, (jsize)0, (jsize)arrayLen, (jbyte *)myname);
 }
env->DeleteLocalRef(byteArray);

byte data[1024];

mfield = env->GetFieldID(testTime, "channelCdata", "[B"); /**********獲取Java的成員以及型別**************/
    jbyteArray chCdata = (jbyteArray)env->GetObjectField(objTestTime, mfield);
    env->GetByteArrayRegion(chCdata, (jsize)0, (jsize)1024, (jbyte *)data);

 env->SetByteArrayRegion(chCdata, (jsize)0, (jsize)1024, (jbyte *)data);/**********訪問Java的成員,設定**************/

}

相關推薦

jni應用如何訪問方法Java

本文將通過例項來說明如何在jni 訪問Java的類和成員。開始先介紹所有物件分類的方法,最後才是例項說明。 訪問物件的屬性和方法 1、例項屬性的訪問   jfieldID  GetFieldID (JNIEnv*env, jclass clazz, const char

java技術學習路徑之:Javaweb監聽器總結應用場景、方法、配置

配置 包名 quest ner web.xml 監聽器接口 tty 數據 XML JavaWeb中,監聽器是一種組件,能夠監聽項目的啟動和停止,用戶會話的創建和銷毀,以及各種組件的添加、更新和刪除,能夠通過監聽對象的狀態改變,自動做出反應執行響應代碼。 應用場景: 啟動網站

最簡單打增量包的方法已附上打包的java

前言: 打增量包的目的是快捷打包出項目兩次更新版本之間的差異檔案(除了打包出新增檔案,還能打包出原有已經被改變的檔案)。 問題1: 打包出這些增量檔案有什麼作用? 答:快速部署這些增量檔案到tomcat的webapps資料夾對應的專案中。進行增量部署。 問題2: 打包的工具是什麼?

Java面向對象繼承、抽象

調用父類 找到 如何 包含 抽取 代碼 創建對象 編號 間接 面向對象 今日內容介紹 u 繼承 u 抽象類 第1章 繼承 1.1 繼承的概念 在現實生活中,繼承一般指的是子女繼承父輩的財產。在程序中,繼承描述的是事物之間的所屬關系,通過繼承可以使多種事物之間形成一種關系體

背水一戰 Windows 10 (73) - 控件控件基: UIElement - 拖放的基本應用, 手動開啟 UIElement 的拖放操作

mar blink don mes read err agent 傳遞 ams 原文:背水一戰 Windows 10 (73) - 控件(控件基類): UIElement - 拖放的基本應用, 手動開啟 UIElement 的拖放操作[源碼下載] 背水一戰 Windows

利用封裝的思想,描述人類這個抽象的屬性方法自擬

void source alt aos print person static his urn package kaoshi; public class two {public static void main(String[] args) { Person xm=new

JS筆記—關於的靜態屬性的繼承call方法的運用

網上看了不少,感覺廢話都太多,抓不住重點,下面單刀直入。 一、先弄清楚對於物件而言call()方法的語法 obj1.obj1's function.call(obj2,parameter1,parameter2,......)      作用:讓obj2代替

少說話多寫程式碼之Python學習050——的成員靜態方法成員方法,getattr,setattr

我們在訪問類的欄位時,還有一些過濾的條件,類似於前端語言比如vue Js、anjularJs中過濾器的概念。在3.0以前可以使用比如,__setattr__,__getattr__的方法進行屬性的過濾。在3.0以後我們如果對某些欄位需要過濾訪問,也可以使用這些函式。 class Rectan

伴生和伴生物件apply方法的實踐

具有相同名字的object和class,分別為伴生物件和伴生類 1 class ApplyTest { //伴生類 2 3 } 4 5 object ApplyTest { //伴生物件 6 7 } 補充程式碼: object ApplyApp { def main(a

java實現錄入學生成績,升序排列後輸出陣列升序 Arrays

Arrays.sort(score) //陣列升序 實現: package com.array.test; import java.util.Arrays; import java.util.Scanner; /** * 錄入學生成績,升序排列後輸出 */

java 獲取 泛型型別介面及超

package generic.portal; /** * Created by Administrator on 2017/1/10. */ public interface GenericInterface<T> { } package gener

bean配置的三種方式XML、註解、Java介紹與對比

如此的話,我們便不在需要在XML當中顯式使用bean來進行bean的配置。Spring容器在初始化的時候便會自動掃描base-package所指定的包以及子包下面的所有class檔案。所有標註為Repository的類將被自動註冊為bean。

org.json.JSONObjectjava使用JSONObject讀取json檔案,出現中文亂碼

出現問題的程式碼 //從json檔案中讀取資料 StringBuffer stringBuffer = new StringBuffer(); try { BufferedReader bufferedReader = new BufferedReader(ne

interface 與abstract class介面 與 抽象的特點以及區別,以及應用場景

一、抽象類(abstract) 1、抽象類不能被例項化,如果例項化就會報錯,編譯無法通過。只有抽象類的非抽象子類可以建立物件。 2、抽象類中不一定含有抽象方法,但是有抽象方法的類一定是抽象類。 3、抽象類中的抽象方法只能宣告,不包含方法體,就是不會給出方法的具體實現

什麼時候使用方法呢?靜態方法何時使用

如果某些操作不依賴具體例項,那它就是靜態的,反之如果某些操作是依賴具體例項的(例如訪問一個特定會員的名稱),那它就應該是例項化的。靜態方法不用new物件可以直接呼叫 1.與類相關與物件無關  2.不需要物件的“輕”方法  3.工廠方法 如果某個方法是用頻率較高,或者方法本身通用性較強,無需初始化類成員變數

Mac電腦使用:您的安全性偏好設定僅允許安裝來自App Store和被認可的開發者的應用解決方法

          昨天準備給電腦上安裝“SEED”,然後別人給我一個壓縮包安裝,結果安裝之後,開啟軟體卻彈出提示框,提示“打不開SEED,因為它來自身份不明的開發者。  。。。”,點選“好”,彈框關閉,SEED卻打不開。         一、 造成有這種提示的原因是由

Java學習筆記31IO:Properties

文本 字符串 存在 設備 操作 筆記 開頭 read 無法 Properties類,表示一個持久的j集,可以存在流中,或者從流中加載   是Hashtable的子類 map集合的方法都能用   用途之一:在開發項目中,我們最後交給客戶的是一個編譯過的class文件,客戶

DelegatingFilterProxy委派過濾器代理使用

targe erp fly lan javaee java ee word tin ava 本文轉自:http://blog.csdn.net/flyingfalcon/article/details/8543898 DelegatingFilterProxy就是一個對於s

Spring Batch 簡單應用CSV文件操作(二)

分享 resultset hunk tid XML component files lin 實現 本文將通過一個完整的實例,與大家一起討論運用Spring Batch對CSV文件的讀寫操作。此實例的流程是:讀取一個含有四個字段的CSV文件(ID,Name,Age,Score

背水一戰 Windows 10 (67) - 控件控件基: DependencyObject - CoreDispatcher, 依賴屬性的設置與獲取, 依賴屬性的變化回調

protected getprop prop 依賴屬性 其他 優先級 dto type 核心 [源碼下載] 背水一戰 Windows 10 (67) - 控件(控件基類): DependencyObject - CoreDispatcher, 依賴屬性的設置與獲取, 依賴