OSDN Git Service

Implement finalizer for RS contexts.
authorJason Sams <jsams@google.com>
Fri, 20 Feb 2015 01:19:52 +0000 (17:19 -0800)
committerJason Sams <jsams@google.com>
Fri, 20 Feb 2015 01:19:52 +0000 (17:19 -0800)
Fixes memory leak when apps forget to call .destroy() on the context.

Change-Id: Ida4685768e92cfe3875da38846d17b86cc386cd0

rs/java/android/renderscript/RenderScript.java

index e7487aa..417bfe2 100644 (file)
@@ -938,6 +938,8 @@ public class RenderScript {
 
     long     mDev;
     long     mContext;
+    private boolean mDestroyed = false;
+
     @SuppressWarnings({"FieldCanBeLocal"})
     MessageThread mMessageThread;
 
@@ -1382,6 +1384,38 @@ public class RenderScript {
         nContextFinish();
     }
 
+    private void helpDestroy() {
+        boolean shouldDestroy = false;
+        synchronized(this) {
+            if (!mDestroyed) {
+                shouldDestroy = true;
+                mDestroyed = true;
+            }
+        }
+
+        if (shouldDestroy) {
+            nContextFinish();
+
+            nContextDeinitToClient(mContext);
+            mMessageThread.mRun = false;
+            try {
+                mMessageThread.join();
+            } catch(InterruptedException e) {
+            }
+
+            nContextDestroy();
+
+            nDeviceDestroy(mDev);
+            mDev = 0;
+        }
+    }
+
+    protected void finalize() throws Throwable {
+        helpDestroy();
+        super.finalize();
+    }
+
+
     /**
      * Destroys this RenderScript context.  Once this function is called,
      * using this context or any objects belonging to this context is
@@ -1390,19 +1424,7 @@ public class RenderScript {
      */
     public void destroy() {
         validate();
-        nContextFinish();
-
-        nContextDeinitToClient(mContext);
-        mMessageThread.mRun = false;
-        try {
-            mMessageThread.join();
-        } catch(InterruptedException e) {
-        }
-
-        nContextDestroy();
-
-        nDeviceDestroy(mDev);
-        mDev = 0;
+        helpDestroy();
     }
 
     boolean isAlive() {