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.
This commit is contained in:
Joel Dice 2011-03-19 15:10:52 -06:00
parent 7004c0ddf3
commit 61552b6b8a
4 changed files with 73 additions and 24 deletions

View File

@ -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 { }

View File

@ -379,6 +379,12 @@ referenceTargetUnreachable(Thread* t, Heap::Visitor* v, object* p)
v->visit(p); v->visit(p);
jreferenceTarget(t, *p) = 0; jreferenceTarget(t, *p) = 0;
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) if (jreferenceQueue(t, *p)
and t->m->heap->status(jreferenceQueue(t, *p)) != Heap::Unreachable) and t->m->heap->status(jreferenceQueue(t, *p)) != Heap::Unreachable)
{ {
@ -400,6 +406,7 @@ referenceTargetUnreachable(Thread* t, Heap::Visitor* v, object* p)
*p = jreferenceVmNext(t, *p); *p = jreferenceVmNext(t, *p);
} }
}
void void
referenceUnreachable(Thread* t, Heap::Visitor* v, object* p) referenceUnreachable(Thread* t, Heap::Visitor* v, object* p)
@ -446,6 +453,7 @@ postVisit(Thread* t, Heap::Visitor* v)
bool major = m->heap->collectionType() == Heap::MajorCollection; bool major = m->heap->collectionType() == Heap::MajorCollection;
assert(t, m->finalizeQueue == 0); assert(t, m->finalizeQueue == 0);
assert(t, m->cleanerQueue == 0);
object firstNewTenuredFinalizer = 0; object firstNewTenuredFinalizer = 0;
object lastNewTenuredFinalizer = 0; object lastNewTenuredFinalizer = 0;
@ -611,13 +619,13 @@ invoke(Thread* t, uintptr_t* arguments)
} }
void 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 (object c = objectClass(t, o); c; c = classSuper(t, c)) {
for (unsigned i = 0; i < arrayLength(t, classMethodTable(t, c)); ++i) { for (unsigned i = 0; i < arrayLength(t, classMethodTable(t, c)); ++i) {
object m = arrayBody(t, classMethodTable(t, c), i); object m = arrayBody(t, classMethodTable(t, c), i);
if (vm::strcmp(reinterpret_cast<const int8_t*>("finalize"), if (vm::strcmp(reinterpret_cast<const int8_t*>(name),
&byteArrayBody(t, methodName(t, m), 0)) == 0 &byteArrayBody(t, methodName(t, m), 0)) == 0
and vm::strcmp(reinterpret_cast<const int8_t*>("()V"), and vm::strcmp(reinterpret_cast<const int8_t*>("()V"),
&byteArrayBody(t, methodSpec(t, m), 0)) == 0) &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); if (not stress) atomicAnd(&(t->flags), ~Thread::StressFlag);
#endif #endif
object f = t->m->finalizeQueue; object finalizeQueue = t->m->finalizeQueue;
PROTECT(t, finalizeQueue);
t->m->finalizeQueue = 0; t->m->finalizeQueue = 0;
for (; f; f = finalizerNext(t, f)) { for (; finalizeQueue; finalizeQueue = finalizerNext(t, finalizeQueue)) {
void (*function)(Thread*, object); void (*function)(Thread*, object);
memcpy(&function, &finalizerFinalize(t, f), BytesPerWord); memcpy(&function, &finalizerFinalize(t, finalizeQueue), BytesPerWord);
if (function) { if (function) {
function(t, finalizerTarget(t, f)); function(t, finalizerTarget(t, finalizeQueue));
} else { } else {
setRoot(t, Machine::ObjectsToFinalize, makePair setRoot(t, Machine::ObjectsToFinalize, makeFinalizeNode
(t, finalizerTarget(t, f), root(t, Machine::ObjectsToFinalize))); (t, finalizerTarget(t, finalizeQueue),
const_cast<char*>("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<char*>("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) { if (root(t, Machine::ObjectsToFinalize) and m->finalizeThread == 0) {
m->finalizeThread = m->processor->makeThread m->finalizeThread = m->processor->makeThread
(m, root(t, Machine::FinalizerThread), m->rootThread); (m, root(t, Machine::FinalizerThread), m->rootThread);
@ -2330,6 +2355,7 @@ Machine::Machine(System* system, Heap* heap, Finder* bootFinder,
finalizers(0), finalizers(0),
tenuredFinalizers(0), tenuredFinalizers(0),
finalizeQueue(0), finalizeQueue(0),
cleanerQueue(0),
weakReferences(0), weakReferences(0),
tenuredWeakReferences(0), tenuredWeakReferences(0),
unsafe(false), unsafe(false),
@ -4099,8 +4125,10 @@ runFinalizeThread(Thread* t)
} }
} }
for (; list; list = pairSecond(t, list)) { for (; list; list = finalizeNodeNext(t, list)) {
finalizeObject(t, pairFirst(t, list)); finalizeObject
(t, finalizeNodeTarget(t, list),
static_cast<const char*>(finalizeNodeMethodName(t, list)));
} }
} }
} }

View File

@ -1311,6 +1311,7 @@ class Machine {
object finalizers; object finalizers;
object tenuredFinalizers; object tenuredFinalizers;
object finalizeQueue; object finalizeQueue;
object cleanerQueue;
object weakReferences; object weakReferences;
object tenuredWeakReferences; object tenuredWeakReferences;
bool unsafe; bool unsafe;

View File

@ -106,6 +106,11 @@
(void* finalize) (void* finalize)
(nogc object next)) (nogc object next))
(type finalizeNode
(object target)
(void* methodName)
(object next))
(type hashMap (type hashMap
(uint32_t size) (uint32_t size)
(object array)) (object array))
@ -294,6 +299,8 @@
(type phantomReference java/lang/ref/PhantomReference) (type phantomReference java/lang/ref/PhantomReference)
(type cleaner sun/misc/Cleaner)
(type byteArray [B (type byteArray [B
(extends jobject) (extends jobject)
(array int8_t body)) (array int8_t body))