/* * Returns true if the reference was registered with a reference queue * and has not yet been enqueued. */ static jboolean isEnqueuable(Env* env, Object* reference) { // This code is a port of the isEnqueuable() function in Android's MarkSweep.cpp assert(reference != NULL); Object* queue = rvmGetObjectInstanceFieldValue(env, reference, java_lang_ref_Reference_queue); Object* queueNext = rvmGetObjectInstanceFieldValue(env, reference, java_lang_ref_Reference_queueNext); return (queue != NULL && queueNext == NULL) ? TRUE : FALSE; }
/* * Removes the reference at the head of a circular queue of * references. */ static Object* dequeuePendingReference(Env* env, Object** list) { // This code is a port of the dequeuePendingReference() function in Android's MarkSweep.cpp assert(list != NULL); assert(*list != NULL); // head = list.pendingNext Object* head = rvmGetObjectInstanceFieldValue(env, *list, java_lang_ref_Reference_pendingNext); Object* ref; if (*list == head) { ref = *list; *list = NULL; } else { // next = head.pendingNext Object* next = rvmGetObjectInstanceFieldValue(env, head, java_lang_ref_Reference_pendingNext); // list.pendingNext = next rvmSetObjectInstanceFieldValue(env, *list, java_lang_ref_Reference_pendingNext, next); ref = head; } rvmSetObjectInstanceFieldValue(env, ref, java_lang_ref_Reference_pendingNext, NULL); return ref; }
/* * Adds a reference to the tail of a circular queue of references. */ static void enqueuePendingReference(Env* env, Object* ref, Object** list) { // This code is a port of the enqueuePendingReference() function in Android's MarkSweep.cpp if (*list == NULL) { // ref.pendingNext = ref rvmSetObjectInstanceFieldValue(env, ref, java_lang_ref_Reference_pendingNext, ref); *list = ref; } else { // head = list.pendingNext Object* head = rvmGetObjectInstanceFieldValue(env, *list, java_lang_ref_Reference_pendingNext); // ref.pendingNext = head rvmSetObjectInstanceFieldValue(env, ref, java_lang_ref_Reference_pendingNext, head); // list.pendingNext = ref rvmSetObjectInstanceFieldValue(env, *list, java_lang_ref_Reference_pendingNext, ref); } }
/* * Unlink the reference list clearing references objects with unreachable * referents. Cleared references registered to a reference queue are * enqueued on the cleared list. */ static void clearAndEnqueueReferences(Env* env, Object** list, Object** cleared) { // This code is a port of the clearWhiteReferences() function in Android's MarkSweep.cpp assert(list != NULL); assert(cleared != NULL); while (*list != NULL) { Object* ref = dequeuePendingReference(env, list); Object* referent = rvmGetObjectInstanceFieldValue(env, ref, java_lang_ref_Reference_referent); if (referent != NULL) { clearReference(env, ref); if (isEnqueuable(env, ref)) { enqueueReference(env, ref, cleared); } } } assert(*list == NULL); }
/* * Enqueues finalizer references with unreachable referents. The * referent is moved to the zombie field (which makes it reachable again), * and the referent field is cleared. */ static void enqueueFinalizerReferences(Env* env, Object** list, Object** cleared) { // This code is a port of the enqueueFinalizerReferences() function in Android's MarkSweep.cpp assert(list != NULL); while (*list != NULL) { Object* ref = dequeuePendingReference(env, list); Object* referent = rvmGetObjectInstanceFieldValue(env, ref, java_lang_ref_Reference_referent); if (referent != NULL) { /* If the referent is non-null the reference must queuable. */ assert(isEnqueuable(env, ref)); // Copy the referent to the zombie field rvmSetObjectInstanceFieldValue(env, ref, java_lang_ref_FinalizerReference_zombie, referent); // Clear the referent clearReference(env, ref); enqueueReference(env, ref, cleared); } } assert(*list == NULL); }
static jobject GetObjectField(JNIEnv* env, jobject obj, jfieldID fieldID) { return (jobject) rvmGetObjectInstanceFieldValue((Env*) env, (Object*) obj, (InstanceField*) fieldID); }