小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

NDK 之 JNI數(shù)據(jù)傳輸

 勤奮不止 2013-05-30

1 基本數(shù)據(jù)類型的傳輸

上層定義一個native的方法,需要一個int 參數(shù) ,返回一個int值

JNI 對應(yīng)上層的方法 , 打印出上層 傳輸下來的 int數(shù)據(jù),并返回 int數(shù)據(jù)

上層 收到 native 方法 返回的 值,在UI中顯示出來

public native int getNumber(int num);

jint
Java_XX_XX_XXActivity_getNumber(JNIEnv* env,jobject thiz,jint num)
{
    if(jniEnv == NULL) {
        jniEnv = env;
    }
    __android_log_print(ANDROID_LOG_INFO, "JNIMsg", "Java -- > C JNI : num = %d",num);
    return num*2;
}

 

2 數(shù)組的傳輸

上層定義一個native的方法,需要一個int數(shù)組,返回一個int數(shù)組

JNI 對應(yīng)上層的方法,取出上層傳遞數(shù)組中的數(shù)據(jù)處理和打印出來,并存入新數(shù)組中,最后把該數(shù)組返回給 Java層

上層 收到 native返回的 數(shù)組,加工成字符串,在UI中顯示出來

public native int[] getArrayNumber(int[] nums);

 

JNIEnv* jniEnv;
 
jintArray
Java_XX_XX_XXActivity_getArrayNumber(JNIEnv* env,jobject thiz,jintArray nums)
{
    if(jniEnv == NULL) {
        jniEnv = env;
    }
    if(nums == NULL){
        return NULL;
    }
    jsize len = (*jniEnv)->GetArrayLength(jniEnv, nums);
    if(len <= 0) {
        return NULL;
    }
    jintArray array = (*jniEnv)->NewIntArray(jniEnv, len);
    if(array == NULL) {
        return NULL;
    }
    // 把 Java 傳遞下來的數(shù)組 用 jint* 存起來
    jint *body = (*env)->GetIntArrayElements(env, nums, 0);
    jint i = 0;
    jint num[len];
    for (; i < len; i++) {
        num[i] = body[i] * 2;
    }
    if(num == NULL){
        return NULL;
    }
//(*env)->GetIntArrayRegion(env,array,start,len,buffer)
// 從start開始復(fù)制長度為len 的數(shù)據(jù)到buffer中
    //給需要返回的數(shù)組賦值
    (*jniEnv)->SetIntArrayRegion(jniEnv,array, 0, len, num);
    return array;
}
 

3   引用數(shù)據(jù)類型

 

String 字符串傳輸

上層定義一個native的方法,需要一個String 參數(shù),返回一個String

JNI對應(yīng)上層的方法,打印出上層傳輸下來的String數(shù)據(jù),并返回處理String數(shù)據(jù)

上層 收到 native 方法 返回的 值,在UI中顯示出來

public native String transferString(String mStrMSG);

jstring
Java_XX_XX_XXActivity_transferString( JNIEnv* env,jobject thiz,jstring msg )
{
    if(jniEnv == NULL) {
        jniEnv = env;
    }
     char data[128];
    memset(data, 0, sizeof(data));
    char *c_msg = NULL;
    c_msg = (char *)(*jniEnv)->GetStringUTFChars(jniEnv, msg, 0);
     __android_log_print(ANDROID_LOG_INFO, "JNIMsg", "C JNI  ---- > %s",c_msg);
     return (*jniEnv)->NewStringUTF(jniEnv, "This is send by C JNI");
}

 

 

自定義對象的傳輸

自定義一個對象Person

上層定義一個native方法,參數(shù)Person,返回值Person

JNI接收對象,打印出相關(guān)信息數(shù)據(jù)

JNI 修改Person 對象數(shù)據(jù),并返回到上層

上層接收到數(shù)據(jù)后 在UI顯示出來

public native Object transferPerson(Person mPerson);     
 
public class Person {
    private String name;
    private int age;
    public Person() {
        name = "";
        age = 0;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    @Override
    public String toString() {
        return "Person [name=" + name + ", age=" + age + "]";
    }
}
 
extern JNIEnv* jniEnv;
jclass Person;
jobject mPerson;
jmethodID getName;
jmethodID setName;
jmethodID toString;
int InitPerson();
void ToString();
void GetName();
void SetName();
 
jobject
Java_XX_XX_XXActivity_transferPerson( JNIEnv* env,jobject thiz,jobject person )
{
    if(jniEnv == NULL) {
        jniEnv = env;
    }
    if (Person == NULL || getName == NULL || setName == NULL || toString == NULL) {
        if (1 != InitPerson()) {
            return NULL;
        }
    }
    mPerson = person;
    if(mPerson == NULL) {
        return NULL;
    }
    GetName();
    GetAge();
    ToString();
    __android_log_print(ANDROID_LOG_INFO, "JNIMsg", "Begin Modify mPerson  .... " );
    SetName();
    SetAge();
    ToString();
    return mPerson;
}
 
int InitPerson() {
    if(jniEnv == NULL) {
        return 0;
    }
    if(Person == NULL) {
        Person = (*jniEnv)->FindClass(jniEnv,"com/XX/Person");
        if(Person == NULL){
            return -1;
        }
    }
    if (getName == NULL) {
        getName = (*jniEnv)->GetMethodID(jniEnv, Person, "getName","()Ljava/lang/String;");
        if (getName == NULL) {
            (*jniEnv)->DeleteLocalRef(jniEnv, Person);
            return -2;
        }
    }
    if (setName == NULL) {
        setName = (*jniEnv)->GetMethodID(jniEnv, Person, "setName","(Ljava/lang/String;)V");
        if (setName == NULL) {
            (*jniEnv)->DeleteLocalRef(jniEnv, Person);
            (*jniEnv)->DeleteLocalRef(jniEnv, getName);
            return -2;
        }
    }
    if (getAge == NULL) {
        getAge = (*jniEnv)->GetMethodID(jniEnv, Person, "getAge","()I");
        if (getAge == NULL) {
            (*jniEnv)->DeleteLocalRef(jniEnv, Person);
            (*jniEnv)->DeleteLocalRef(jniEnv, getName);
            (*jniEnv)->DeleteLocalRef(jniEnv, setName);
            return -2;
        }
    }
    if (setAge == NULL) {
        setAge = (*jniEnv)->GetMethodID(jniEnv, Person, "setAge","(I)V");
        if (setAge == NULL) {
            (*jniEnv)->DeleteLocalRef(jniEnv, Person);
            (*jniEnv)->DeleteLocalRef(jniEnv, getName);
            (*jniEnv)->DeleteLocalRef(jniEnv, setName);
            (*jniEnv)->DeleteLocalRef(jniEnv, getAge);
            return -2;
        }
    }
    if (toString == NULL) {
        toString = (*jniEnv)->GetMethodID(jniEnv, Person, "toString","()Ljava/lang/String;");
        if (toString == NULL) {
            (*jniEnv)->DeleteLocalRef(jniEnv, Person);
            (*jniEnv)->DeleteLocalRef(jniEnv, getName);
            (*jniEnv)->DeleteLocalRef(jniEnv, setName);
            (*jniEnv)->DeleteLocalRef(jniEnv, getAge);
            (*jniEnv)->DeleteLocalRef(jniEnv, setAge);
            return -2;
        }
    }
    return 1;
}
/**
* GetName  對應(yīng)Person的getName方法
*/
void GetName() {
    if(Person == NULL || getName == NULL) {
        if(1 != InitPerson()){
            return;
        }
    }
    //調(diào)用方法
    jstring jstr = (*jniEnv)->CallObjectMethod(jniEnv, mPerson, getName);
    char* cstr = (char*) (*jniEnv)->GetStringUTFChars(jniEnv,jstr, 0);
    __android_log_print(ANDROID_LOG_INFO, "JNIMsg", "getName  ---- >  %s",cstr );
    //釋放資源
    (*jniEnv)->ReleaseStringUTFChars(jniEnv, jstr, cstr);
    (*jniEnv)->DeleteLocalRef(jniEnv, jstr);
}
/**
* GetAge 對應(yīng)Person的getName方法
*/
void GetAge() {
    if(Person == NULL || getName == NULL) {
        if(1 != InitPerson()){
            return;
        }
    }
    //調(diào)用方法
    jint age = (*jniEnv)->CallIntMethod(jniEnv, mPerson, getAge);
    __android_log_print(ANDROID_LOG_INFO, "JNIMsg", "getAge  ---- >  %d",age );
}
/**
* SetName 對應(yīng)Person的setName方法
*/
void SetName() {
    if(Person == NULL || setName == NULL) {
        if(1 != InitPerson()){
            return;
        }
    }
    jstring jstr = (*jniEnv)->NewStringUTF(jniEnv, "Modify Name");
    //調(diào)用方法
    (*jniEnv)->CallVoidMethod(jniEnv, mPerson, setName,jstr);
    (*jniEnv)->DeleteLocalRef(jniEnv, jstr);
}
int age = 20;
/**
* SetAge 對應(yīng)Person的setAge方法
*/
void SetAge() {
    if(Person == NULL || setAge == NULL) {
        if(1 != InitPerson()){
            return;
        }
    }
    //調(diào)用方法
    (*jniEnv)->CallVoidMethod(jniEnv, mPerson, setAge,age++);
}
/**
* ToString 對應(yīng) Person 的 toString 方法 , 打印出相關(guān)信息
*/
void ToString() {
    if(Person == NULL || toString == NULL) {
        if(1 != InitPerson()){
            return;
        }
    }
    jstring jstr = NULL;
    char* cstr = NULL;
    //調(diào)用方法
    jstr = (*jniEnv)->CallObjectMethod(jniEnv, mPerson, toString);
    cstr = (char*) (*jniEnv)->GetStringUTFChars(jniEnv,jstr, 0);
    __android_log_print(ANDROID_LOG_INFO, "JNIMsg", "C JNI toString  ---- >  %s",cstr );
    (*jniEnv)->ReleaseStringUTFChars(jniEnv, jstr, cstr);
    (*jniEnv)->DeleteLocalRef(jniEnv, jstr);
}
 
 

5 資源釋放

JNI 基本數(shù)據(jù)類型是不需要釋放的, 如 jint , jlong , jchar 等等 。

我們需要釋放是引用數(shù)據(jù)類型,當(dāng)然也包括數(shù)組家族。如:jstring ,jobject ,jobjectArray,jintArray 等等。

當(dāng)然,大家可能經(jīng)常忽略掉的是 jclass ,jmethodID , 這些也是需要釋放的

 

Native Code 本身的內(nèi)存泄漏

JNI 編程首先是一門具體的編程語言,或者 C 語言,或者 C++,或者匯編,或者其它 native 的編程語言。每門編程語言環(huán)境都實(shí)現(xiàn)了自身的內(nèi)存管理機(jī)制。因此,JNI 程序開發(fā)者要遵循 native 語言本身的內(nèi)存管理機(jī)制,避免造成內(nèi)存泄漏。以 C 語言為例,當(dāng)用 malloc() 在進(jìn)程堆中動態(tài)分配內(nèi)存時,JNI 程序在使用完后,應(yīng)當(dāng)調(diào)用 free() 將內(nèi)存釋放??傊性?native 語言編程中應(yīng)當(dāng)注意的內(nèi)存泄漏規(guī)則,在 JNI 編程中依然適應(yīng)。

Native 語言本身引入的內(nèi)存泄漏會造成 native memory 的內(nèi)存,嚴(yán)重情況下會造成 native memory 的 out of memory。

Global Reference 引入的內(nèi)存泄漏

JNI 編程還要同時遵循 JNI 的規(guī)范標(biāo)準(zhǔn),JVM 附加了 JNI 編程特有的內(nèi)存管理機(jī)制。

JNI 中的 Local Reference 只在 native method 執(zhí)行時存在,當(dāng) native method 執(zhí)行完后自動失效。這種自動失效,使得對 Local Reference 的使用相對簡單,native method 執(zhí)行完后,它們所引用的 Java 對象的 reference count 會相應(yīng)減 1。不會造成 Java Heap 中 Java 對象的內(nèi)存泄漏。

而 Global Reference 對 Java 對象的引用一直有效,因此它們引用的 Java 對象會一直存在 Java Heap 中。程序員在使用 Global Reference 時,需要仔細(xì)維護(hù)對 Global Reference 的使用。如果一定要使用 Global Reference,務(wù)必確保在不用的時候刪除。就像在 C 語言中,調(diào)用 malloc() 動態(tài)分配一塊內(nèi)存之后,調(diào)用 free() 釋放一樣。否則,Global Reference 引用的 Java 對象將永遠(yuǎn)停留在 Java Heap 中,造成 Java Heap 的內(nèi)存泄漏。

 

釋放String

jstring jstr = NULL;

char* cstr = NULL;

//調(diào)用方法

jstr = (*jniEnv)->CallObjectMethod(jniEnv, mPerson, getName);

cstr = (char*) (*jniEnv)->GetStringUTFChars(jniEnv,jstr, 0);

__android_log_print(ANDROID_LOG_INFO, "JNIMsg", "getName  ---->  %s",cstr );

//釋放資源

(*jniEnv)->ReleaseStringUTFChars(jniEnv, jstr, cstr);

(*jniEnv)->DeleteLocalRef(jniEnv, jstr);

釋放 類 、對象、方法

(*jniEnv)->DeleteLocalRef(jniEnv, XXX);//“XXX” 代表 引用對象

釋放 數(shù)組家族

jclass jclsStr = (*jniEnv)->FindClass(jniEnv, "java/lang/String");

jobjectArray arrays = (*jniEnv)->NewObjectArray(jniEnv, len, jclsStr, 0);

(*jniEnv)->DeleteLocalRef(jniEnv, jclsStr);  //釋放String類

(*jniEnv)->DeleteLocalRef(jniEnv, arrays); //釋放jobjectArray數(shù)組

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

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多