Jni如何傳遞並且修改兩個基礎參數

來源:互聯網
上載者:User

標籤:android   style   blog   http   color   io   os   使用   java   

最近在開發jni時,需要返回多個參數給java。這個過程中,碰到了一些問題,值得探討一下。

 具體是這樣,jni方法jni_do_something作了底層處理後,得出兩個int資料,需要將他們的值傳遞給java。在C語言中,直接用指標就可以了。Java中可以傳遞兩個Integer的引用。用JNI怎麼實現呢?我在android frameworks原始碼中看了一下,對於類似傳值需求,android都是在java層自訂了一個class,用來封裝各個需要傳遞的參數。jni中需要修改時,獲得該class的成員id,然後用SetIntField來修改。
 我不想這麼做,因為類似的native方法比較多,我總不能每次都定義結構體吧,而且將不同方法的參數封裝在一個class中,也不太對,因為它們沒有共同意義。
為了讓jni能修改,Java層毫無疑問需要傳入Integer型別參數,這樣jni才認為它是一個jobject,才可以修改。好的,問題出現了。jni方法實現:
jni_do_something(JNIEnv *env, jobject thiz, jobject p1, jobject p2) {    jclass c;    jfieldID id;    c = env->FindClass("java/lang/Integer");    if (c==NULL)    {        LOGD("FindClass failed");        return -1;    }    id = env->GetFieldID(c, "value", "I");    if (id==NULL)    {        LOGD("GetFiledID failed");        return -1;    }    env->SetIntField(p1, id, 5);    env->SetIntField(p2, id, 10);    return 0;}

java層調用如果這樣寫:

native int do_something(Integer p1, Integer p2);Integer p1=0, p2=0;do_something(p1, p2);Log.d("test", "p1: "+p1);Log.d("test", "p2: "+p2);

這樣列印出的值是(10,10),而不是期望的(5,10)。為什麼呢?

我在stackoverflow上發了一個貼,大家眾說紛紜。有的說跟mutable/imutable object有關,有的說跟autoboxing有關。我再次做了實驗。如果寫成:
Integer p1=0, p2=1;
或者:
Integer p1 = new Integer(0);Integer p2 = new Integer(0);
則列印的是預期結果。 原來,這跟autoboxing有關。當你用Integer p1 = 0這種方式時,java使用autoboxing機制將0封裝在一個Integer對象中,這時使用了Integer類的valueOf方法。在java 語言中,有一個很詭異的現象,對於在-128~127間的小數字,會在static pool中返回一個靜態對象,在這個範圍外的,會new一個Integer。 可以參考這個連結:http://stackoverflow.com/questions/1995113/strangest-language-feature574: Fun with auto boxing and the integer cache in Java
/** * Returns a <tt>Integer</tt> instance representing the specified * <tt>int</tt> value. * If a new <tt>Integer</tt> instance is not required, this method * should generally be used in preference to the constructor * {@link #Integer(int)}, as this method is likely to yield * significantly better space and time performance by caching * frequently requested values. * * @param  i an <code>int</code> value. * @return a <tt>Integer</tt> instance representing <tt>i</tt>. * @since  1.5 */public static Integer valueOf(int i) {    if (i >= -128 && i <= IntegerCache.high)        return IntegerCache.cache[i + 128];    else        return new Integer(i);}

回到程式中來,如果寫成Integer p0 = 0, p1 = 0,它們是static pool中同一個對象的引用,因此jni中修改的是同一個對象。正確做法應該是使用new。

 

Jni如何傳遞並且修改兩個基礎參數

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.