歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
您现在的位置: Linux教程網 >> UnixLinux >  >> Linux編程 >> Linux編程

Android - 編寫強引用Java對象

JAVA有個垃圾回收機制,沒有引用的對象會被虛擬機在整理內存時進行回收,所以使用弱引用java對象時,而實際調用為持久對象時將會出現問題。並且這個問題有時會隨機出現,這個會內存整理回收時機有關。

下面,說下對於在JNI中使用JAVA中對象代碼編寫方法:

JAVA類方法編寫:

  1. public class TestModule{  
  2.     static native boolean native_init(WeakReference<TestModule> wo);  
  3.       
  4.     /* 構造函數中傳遞JAVA弱應用對象給JNI層 */  
  5.     public TestModule() {  
  6.         native_init(new WeakReference<TestModule>(this));  
  7.     }  
  8.   
  9.     ...  
  10.       
  11.     /* 提供給JNI調用的JAVA方法 */  
  12.     static String native_callback(Object wo, int i, String json) {  
  13.         try {  
  14.             WeakReference<CDCAModule> r = (WeakReference<TestModule>) wo;  
  15.             CDCAModule m = r.get();  
  16.             if (m != null)  
  17.                 return m.callback.callback(i, json);  
  18.         } catch (Throwable e) {  
  19.             e.printStackTrace();  
  20.         }  
  21.         return null;  
  22.     }  
  23. }  

JNI 編寫方法:

  1. static jobject   g_java_peer = NULL;  
  2. static jmethodID g_callback = NULL;  
  3.   
  4. /* 對應JAVA層native_init函數 */  
  5. JNIEXPORT jboolean JNICALL Java_com_test_TestModule_native_init(JNIEnv *e,  
  6.         jclass clazz, jobject wo) {  
  7.     if (wo == NULL)  
  8.         throw_runtime_exception(e, "");  
  9.           
  10.     /** 
  11.      * 如果這個JAVA對象,垃圾回收時不予釋放掉,使用弱引用轉換成強引用對象,如此 
  12.      *  則僅用戶進行主動釋放時此對象才無效 
  13.      */  
  14.     if (g_java_peer == NULL)  
  15.         g_java_peer = e->NewGlobalRef(wo);  
  16.   
  17.     /* 獲取得到JAVA中定義的方法 */  
  18.     if ((g_callback = e->GetStaticMethodID(clazz, "native_callback",  
  19.             "Ljava/lang/Object;ILjava/lang/String")) == NULL)  
  20.         return JNI_FALSE;  
  21.     return JNI_TRUE;  
  22. }  
  23.   
  24. char*jniCallJavaTestModuleMethod(int id, const char*json, char*buf, int len) {  
  25.     JNIEnv*e = NULL;  
  26.     jstring ret = NULL;  
  27.     char *p = NULL;  
  28.     int rlen;  
  29.   
  30.     if (id < 0 || buf == NULL || len <= 0)  
  31.         return NULL;  
  32.     /* 這裡注意,JNIEnv是一個線程相關的變量,所以使用javaAttachThread保證取得當前線程的Jni環境變量*/  
  33.     if ((e = javaAttachThread("test-thread")) == NULL)  
  34.         return NULL;  
  35.           
  36.     /* 調用JAVA方法 */  
  37.     if ((ret = (jstring) e->CallStaticObjectMethod((jclass)g_java_peer, g_callback,  
  38.             json ? e->NewStringUTF(json) : NULL)) == NULL)  
  39.         return NULL;  
  40.     p = buf;  
  41.     if ((rlen = e->GetStringLength(ret)) > len) {  
  42.         char*p = (char*)calloc(1,rlen);  
  43.         if (p == NULL)  
  44.             return NULL;  
  45.     }  
  46.     e->GetStringUTFRegion(ret, 0, rlen, p);  
  47.     return p;  
  48. }

在JNI中提供三種類型的引用:

1、Local Reference 本地引用,函數調用時傳入jobject或者jni函數創建的jobejct,其特點就是一旦JNI層函數返回,jobject就被垃圾回收掉,所以需要注意其生命周期。可以強制調用DeleteLocalRef進行立即回收。

jstring pathStr = env->NewStringUTF(path)

....

env->DeleteLocalRef(pathStr);

2、Global Reference 全局引用 ,這種對象如不主動釋放,它永遠都不會被垃圾回收

創建: env->NewGlobalRef(obj);

釋放: env->DeleteGlobalRef(obj)

3、Weak Global Reference 弱全局引用,一種特殊的 Global Reference ,在運行過程中可能被垃圾回收掉,所以使用時請務必注意其生命周期及隨時可能被垃圾回收掉,比如內存不足時。

使用前可以利用JNIEnv的 IsSameObject 進行判定它是否被回收

env->IsSameObject(obj1,obj2);

更多Android相關信息見Android 專題頁面 http://www.linuxidc.com/topicnews.aspx?tid=11

Copyright © Linux教程網 All Rights Reserved