package org.gscript.jni; import java.lang.ref.ReferenceQueue; import java.lang.ref.WeakReference; import java.util.ArrayList; import java.util.List; import android.util.Log; class WeakJNIReference extends WeakReference<JNIReference> { private static final String LOG_TAG = "WeakJNIReference"; static private ReferenceQueue<JNIReference> sRefQueue = new ReferenceQueue<JNIReference>(); static private List<WeakJNIReference> sRefList = new ArrayList<WeakJNIReference>(); private final long mPointer; WeakJNIReference(JNIReference object) { super(object, sRefQueue); this.mPointer = object.getReferencePointer(); /* add our self to the list of weak references so that * we can verify existance when disposing */ synchronized (sRefList) { sRefList.add(this); } } void dispose() { synchronized (sRefList) { if (sRefList.remove(this)) { Log.v(LOG_TAG, "Disposing JNIReference"); JNIReference.nativeDispose(mPointer); } } } static ReferenceQueue<JNIReference> referenceQueue() { return sRefQueue; } /* Garbage collection */ private static Runnable sCollectRunnable = new Runnable() { public void run() { ReferenceQueue<JNIReference> refQueue = WeakJNIReference .referenceQueue(); while (true) { WeakJNIReference weakRefObject; try { // remove is blocking until a reference becomes available Object reference = refQueue.remove(); if (reference != null) { weakRefObject = (WeakJNIReference) reference; weakRefObject.dispose(); Log.v(LOG_TAG, "Disposed reference " + weakRefObject.mPointer); } } catch (InterruptedException e) { } } }; }; static final String THREAD_NAME = "JNIRefCollector"; private static Thread sJNICollectThread = new Thread(sCollectRunnable, THREAD_NAME); static { sJNICollectThread .setPriority(android.os.Process.THREAD_PRIORITY_BACKGROUND); sJNICollectThread.start(); } }