java native interface JNI 調用Java方法

來源:互聯網
上載者:User

標籤:reg   str   static   傳回值   jpg   release   family   tab   pre   

在上一篇文章中介紹了JNI。以及java調用JNI。這篇講一下 JNI調用java方法。

      通過使用合適的JNI函數,你能夠建立Java對象,get、set 靜態(static)和 執行個體(instance)的域,調用靜態(static)和執行個體(instance)函數。

JNI通過ID識別域和方法。一個域或方法的ID是不論什麼處理域和方法的函數的必須參數。
下表列出了用以得到靜態(static)和執行個體(instance)的域與方法的JNI函數。每一個函數接受(作為參數)域或方法的類,它們的名稱,符號和它們相應返回的jfieldID或jmethodID。

函數  描寫敘述
GetFieldID  得到一個執行個體的域的ID
GetStaticFieldID  得到一個靜態域的ID
GetMethodID 得到一個執行個體的方法的ID
GetStaticMethodID 得到一個靜態方法的ID

構造一個Java對象的執行個體


jclass cls = (*env)->FindClass(env, "Lpackagename/classname;");  //建立一個class的引用
jmethodID id = (*env)->GetMethodID(env, cls, "", "(D)V");  //注意這裡方法的名稱是"",它表示這是一個建構函式。並且構造參數是double型的
jobject obj = (*env)->NewObjectA(env, cls, id, args);  //獲得一執行個體,args是建構函式的參數,它是一個jvalue*類型。

首先是獲得一個Java類的class引用 (*env)->FindClass(env, "Lpackagename/classname;");  請注意參數:Lpackagename/classname; 。L代表這是在描寫敘述一個物件類型,packagename/classname是該對象耳朵class路徑,請注意一定要以分號(;)結束!

然後是擷取函數的id。jmethodID id = env->GetMethodID(cls, "", "(D)V");  第一個是剛剛獲得的class引用,第二個是方法的名稱,最後一個就是方法的簽名


難理解的函數簽名

JNINativeMethod的定義例如以下:


   jclass cls = (*env)->FindClass(env, "Lpackagename/classname;");  //建立一個class的引用
   jmethodID id = (*env)->GetMethodID(env, cls, "", "(D)V");  //注意這裡方法的名稱是"",它表示這是一個建構函式。      並且構造參數是double型的
    jobject obj = (*env)->NewObjectA(env, cls, id, args);  //獲得一執行個體。args是建構函式的參數,它是一個jvalue*類型。

第一個變數name是Java中函數的名字。 
第二個變數signature,用字串是描寫敘述了函數的參數和傳回值 
第三個變數fnPtr是函數指標。指向C函數。

 

當中比較難以理解的是第二個參數。比如
"()V"
"(II)V"
"(Ljava/lang/String;Ljava/lang/String;)V"


實際上這些字元是與函數的參數類型一一相應的。
"()" 中的字元表示參數。後面的則代表傳回值。比如"()V" 就表示void Func();
"(II)V" 表示 void Func(int, int);

 

那其它情況呢?請查看下錶:

類型 符號
boolean Z
byte B
char C
short S
int I
long L
float F
double D
void V
object對象 LClassName;      L類名;
Arrays [array-type        [數群組類型
methods方法 (argument-types)return-type     (參數類型)傳回型別


稍稍補充一下:

1、方法參數或者傳回值為java中的對象時,簽名中必須以“L”加上其路徑,只是此路徑必須以“/”分開。自己定義的對象也使用本規則

比方說 java.lang.String為“java/lang/String”,com.nedu.jni.helloword.Student為"Lcom /nedu/jni/helloword/Student;"

2、方法參數或者傳回值為數群組類型時,請前加上[

比如[I表示 int[],[[[D表示 double[][][]。即幾維數組就加幾個[

在本地方法中調用Java對象的方法1、擷取你須要訪問的Java對象的類:jclass cls = (*env)->GetObjectClass(env, obj);       // 使用GetObjectClass方法擷取obj相應的jclass。 
jclass cls = (*env)->FindClass(“android/util/log”) // 直接搜尋類名,須要是static修飾的類。

2、擷取MethodID:jmethodID mid = (*env)->GetMethodID(env, cls, "callback", "(I)V"); //GetStaticMethodID(…)。擷取靜態方法的ID使用GetMethdoID方法擷取你要使用的方法的MethdoID

其參數的意義: 
env-->JNIEnv 
cls-->第一步擷取的jclass 
"callback"-->要調用的方法名 
"(I)V"-->方法的Signature, 簽名同前面的JNI規則。

3、調用方法:(*env)->CallVoidMethod(env, obj, mid, depth);// CallStaticIntMethod(….) , 調用靜態方法

使用CallVoidMethod方法調用方法。參數的意義: 
env-->JNIEnv 
obj-->通過本地方法穿過來的jobject 
mid-->要調用的MethodID(即第二步獲得的MethodID) 
depth-->方法須要的參數(相應方法的需求,加入相應的參數)

 

註:這裡使用的是CallVoidMethod方法調用,由於沒有傳回值,假設有傳回值的話使用相應的方法。在後面會提到。

CallVoidMethod                   CallStaticVoidMethod
CallIntMethod                     CallStaticVoidMethod
CallBooleanMethod              CallStaticVoidMethod
CallByteMethod                   CallStaticVoidMethod

Jni操作Java的String對象

從java程式中傳過去的String對象在本地方法中相應的是jstring類型,jstring類型和c中的char*不同。所以假設你直接當做char*使用的話,就會出錯。

因此在使用之前須要將jstring轉換成為c/c++中的char*,這裡使用JNIEnv提供的方法轉換。

const char *str = (*env)->GetStringUTFChars(env, jstr, 0);(*env)->ReleaseStringUTFChars(env, jstr, str);

這裡使用GetStringUTFChars方法將傳進來的prompt(jstring類型)轉換成為UTF-8的格式,就行在本地方法中使用了。


注意:在使用完你所轉換之後的對象之後,須要顯示調用ReleaseStringUTFChars方法。讓JVM釋放轉換成UTF-8的string的對象的空間。假設不顯示的調用的話。JVM中會一直儲存該對象,不會被記憶體回收行程回收,因此就會導致記憶體溢出。

以下是Jni訪問String對象的一些方法:

  • GetStringUTFChars          將jstring轉換成為UTF-8格式的char*
  • GetStringChars               將jstring轉換成為Unicode格式的char*
  • ReleaseStringUTFChars    釋放指向UTF-8格式的char*的指標
  • ReleaseStringChars         釋放指向Unicode格式的char*的指標
  • NewStringUTF               建立一個UTF-8格式的String對象
  • NewString                    建立一個Unicode格式的String對象
  • GetStringUTFLength      擷取UTF-8格式的char*的長度
  • GetStringLength           擷取Unicode格式的char*的長度

以下提供兩個String對象和char*互轉的方法:

/* c/c++ string turn to java jstring */
jstring charToJstring(JNIEnv* env, const char* pat)
{
jclass     strClass = (*env)->FindClass(env, "java/lang/String");
jmethodID  ctorID   = (*env)->GetMethodID(env, strClass, "", "([BLjava/lang/String;)V");
jbyteArray bytes    = (*env)->NewByteArray(env, strlen(pat));
(*env)->SetByteArrayRegion(env, bytes, 0, strlen(pat), (jbyte*)pat);
jstring    encoding = (*env)->NewStringUTF(env, "UTF-8");
return (jstring)(*env)->NewObject(env, strClass, ctorID, bytes, encoding);
}


/* java jstring turn to c/c++ char* */
char* jstringToChar(JNIEnv* env, jstring jstr)
{       
    char* pStr = NULL;
    jclass     jstrObj   = (*env)->FindClass(env, "java/lang/String");
    jstring    encode    = (*env)->NewStringUTF(env, "utf-8");
    jmethodID  methodId  = (*env)->GetMethodID(env, jstrObj, "getBytes", "(Ljava/lang/String;)[B");
    jbyteArray byteArray = (jbyteArray)(*env)->CallObjectMethod(env, jstr, methodId, encode);
    jsize      strLen    = (*env)->GetArrayLength(env, byteArray);
    jbyte      *jBuf     = (*env)->GetByteArrayElements(env, byteArray, JNI_FALSE);
    if (jBuf > 0)
    {
        pStr = (char*)malloc(strLen + 1);
        if (!pStr)
        {
            return NULL;
        }
        memcpy(pStr, jBuf, strLen);
        pStr[strLen] = 0;
    }
    env->ReleaseByteArrayElements(byteArray, jBuf, 0);
    return pStr;
}

事實上在JNI中調用java的特性和在java中區別不大都是同樣思想,比方先找類。再找構造,再建立對象。然後就進行一系列操作...等等。

參考:http://zhiweiofli.iteye.com/blog/1830321

如有問題請留言,轉載註明出處。

java native interface JNI 調用Java方法

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.