From 61552b6b8afda786a93c27eb3f97dad505c9652d Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Sat, 19 Mar 2011 15:10:52 -0600 Subject: [PATCH] check for and handle instances of sun.misc.Cleaner during GC OpenJDK uses an alternative to Object.finalize for resource cleanup in the form of sun.misc.Cleaner. Normally, OpenJDK's java.lang.ref.Reference.ReferenceHandler thread handles this, calling Cleaner.clean on any instances it finds in its "pending" queue. However, Avian handles reference queuing internally, so it never actually adds anything to that queue, so the VM must call Cleaner.clean itself. --- classpath/sun/misc/Cleaner.java | 13 ++++++ src/machine.cpp | 76 ++++++++++++++++++++++----------- src/machine.h | 1 + src/types.def | 7 +++ 4 files changed, 73 insertions(+), 24 deletions(-) create mode 100644 classpath/sun/misc/Cleaner.java diff --git a/classpath/sun/misc/Cleaner.java b/classpath/sun/misc/Cleaner.java new file mode 100644 index 0000000000..d4dd733f48 --- /dev/null +++ b/classpath/sun/misc/Cleaner.java @@ -0,0 +1,13 @@ +/* Copyright (c) 2011, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package sun.misc; + +public class Cleaner { } diff --git a/src/machine.cpp b/src/machine.cpp index f59d672434..9b23e72e8a 100644 --- a/src/machine.cpp +++ b/src/machine.cpp @@ -379,26 +379,33 @@ referenceTargetUnreachable(Thread* t, Heap::Visitor* v, object* p) v->visit(p); jreferenceTarget(t, *p) = 0; - if (jreferenceQueue(t, *p) - and t->m->heap->status(jreferenceQueue(t, *p)) != Heap::Unreachable) - { - // queue is reachable - add the reference + if (objectClass(t, *p) == type(t, Machine::CleanerType)) { + object reference = *p; + *p = jreferenceVmNext(t, reference); + jreferenceVmNext(t, reference) = t->m->cleanerQueue; + t->m->cleanerQueue = reference; + } else { + if (jreferenceQueue(t, *p) + and t->m->heap->status(jreferenceQueue(t, *p)) != Heap::Unreachable) + { + // queue is reachable - add the reference - v->visit(&jreferenceQueue(t, *p)); + v->visit(&jreferenceQueue(t, *p)); - object q = jreferenceQueue(t, *p); + object q = jreferenceQueue(t, *p); - if (referenceQueueFront(t, q)) { - set(t, *p, JreferenceJNext, referenceQueueFront(t, q)); - } else { - set(t, *p, JreferenceJNext, *p); + if (referenceQueueFront(t, q)) { + set(t, *p, JreferenceJNext, referenceQueueFront(t, q)); + } else { + set(t, *p, JreferenceJNext, *p); + } + set(t, q, ReferenceQueueFront, *p); + + jreferenceQueue(t, *p) = 0; } - set(t, q, ReferenceQueueFront, *p); - jreferenceQueue(t, *p) = 0; + *p = jreferenceVmNext(t, *p); } - - *p = jreferenceVmNext(t, *p); } void @@ -446,6 +453,7 @@ postVisit(Thread* t, Heap::Visitor* v) bool major = m->heap->collectionType() == Heap::MajorCollection; assert(t, m->finalizeQueue == 0); + assert(t, m->cleanerQueue == 0); object firstNewTenuredFinalizer = 0; object lastNewTenuredFinalizer = 0; @@ -611,13 +619,13 @@ invoke(Thread* t, uintptr_t* arguments) } void -finalizeObject(Thread* t, object o) +finalizeObject(Thread* t, object o, const char* name) { for (object c = objectClass(t, o); c; c = classSuper(t, c)) { for (unsigned i = 0; i < arrayLength(t, classMethodTable(t, c)); ++i) { object m = arrayBody(t, classMethodTable(t, c), i); - if (vm::strcmp(reinterpret_cast("finalize"), + if (vm::strcmp(reinterpret_cast(name), &byteArrayBody(t, methodName(t, m), 0)) == 0 and vm::strcmp(reinterpret_cast("()V"), &byteArrayBody(t, methodSpec(t, m), 0)) == 0) @@ -2254,19 +2262,36 @@ doCollect(Thread* t, Heap::CollectionType type) if (not stress) atomicAnd(&(t->flags), ~Thread::StressFlag); #endif - object f = t->m->finalizeQueue; + object finalizeQueue = t->m->finalizeQueue; + PROTECT(t, finalizeQueue); t->m->finalizeQueue = 0; - for (; f; f = finalizerNext(t, f)) { + for (; finalizeQueue; finalizeQueue = finalizerNext(t, finalizeQueue)) { void (*function)(Thread*, object); - memcpy(&function, &finalizerFinalize(t, f), BytesPerWord); + memcpy(&function, &finalizerFinalize(t, finalizeQueue), BytesPerWord); if (function) { - function(t, finalizerTarget(t, f)); + function(t, finalizerTarget(t, finalizeQueue)); } else { - setRoot(t, Machine::ObjectsToFinalize, makePair - (t, finalizerTarget(t, f), root(t, Machine::ObjectsToFinalize))); + setRoot(t, Machine::ObjectsToFinalize, makeFinalizeNode + (t, finalizerTarget(t, finalizeQueue), + const_cast("finalize"), + root(t, Machine::ObjectsToFinalize))); } } + object cleanerQueue = t->m->cleanerQueue; + PROTECT(t, cleanerQueue); + t->m->cleanerQueue = 0; + while (cleanerQueue) { + setRoot(t, Machine::ObjectsToFinalize, makeFinalizeNode + (t, cleanerQueue, + const_cast("clean"), + root(t, Machine::ObjectsToFinalize))); + + object tmp = cleanerQueue; + cleanerQueue = jreferenceVmNext(t, cleanerQueue); + jreferenceVmNext(t, tmp) = 0; + } + if (root(t, Machine::ObjectsToFinalize) and m->finalizeThread == 0) { m->finalizeThread = m->processor->makeThread (m, root(t, Machine::FinalizerThread), m->rootThread); @@ -2330,6 +2355,7 @@ Machine::Machine(System* system, Heap* heap, Finder* bootFinder, finalizers(0), tenuredFinalizers(0), finalizeQueue(0), + cleanerQueue(0), weakReferences(0), tenuredWeakReferences(0), unsafe(false), @@ -4099,8 +4125,10 @@ runFinalizeThread(Thread* t) } } - for (; list; list = pairSecond(t, list)) { - finalizeObject(t, pairFirst(t, list)); + for (; list; list = finalizeNodeNext(t, list)) { + finalizeObject + (t, finalizeNodeTarget(t, list), + static_cast(finalizeNodeMethodName(t, list))); } } } diff --git a/src/machine.h b/src/machine.h index dca89f1637..23b4d3b943 100644 --- a/src/machine.h +++ b/src/machine.h @@ -1311,6 +1311,7 @@ class Machine { object finalizers; object tenuredFinalizers; object finalizeQueue; + object cleanerQueue; object weakReferences; object tenuredWeakReferences; bool unsafe; diff --git a/src/types.def b/src/types.def index 8b8d980ffc..d68fc7436a 100644 --- a/src/types.def +++ b/src/types.def @@ -106,6 +106,11 @@ (void* finalize) (nogc object next)) +(type finalizeNode + (object target) + (void* methodName) + (object next)) + (type hashMap (uint32_t size) (object array)) @@ -294,6 +299,8 @@ (type phantomReference java/lang/ref/PhantomReference) +(type cleaner sun/misc/Cleaner) + (type byteArray [B (extends jobject) (array int8_t body))