歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux編程 >> Linux編程 >> Android - 編寫強引用Java對象

Android - 編寫強引用Java對象

日期:2017/3/1 10:22:07   编辑:Linux編程

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

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

JAVA類方法編寫:

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

JNI 編寫方法:

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

在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