mirror of
https://github.com/corda/corda.git
synced 2025-02-14 14:42:32 +00:00
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:
parent
7004c0ddf3
commit
61552b6b8a
13
classpath/sun/misc/Cleaner.java
Normal file
13
classpath/sun/misc/Cleaner.java
Normal 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 { }
|
@ -379,26 +379,33 @@ referenceTargetUnreachable(Thread* t, Heap::Visitor* v, object* p)
|
|||||||
v->visit(p);
|
v->visit(p);
|
||||||
jreferenceTarget(t, *p) = 0;
|
jreferenceTarget(t, *p) = 0;
|
||||||
|
|
||||||
if (jreferenceQueue(t, *p)
|
if (objectClass(t, *p) == type(t, Machine::CleanerType)) {
|
||||||
and t->m->heap->status(jreferenceQueue(t, *p)) != Heap::Unreachable)
|
object reference = *p;
|
||||||
{
|
*p = jreferenceVmNext(t, reference);
|
||||||
// queue is reachable - add the 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)) {
|
if (referenceQueueFront(t, q)) {
|
||||||
set(t, *p, JreferenceJNext, referenceQueueFront(t, q));
|
set(t, *p, JreferenceJNext, referenceQueueFront(t, q));
|
||||||
} else {
|
} else {
|
||||||
set(t, *p, JreferenceJNext, *p);
|
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
|
void
|
||||||
@ -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)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
@ -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))
|
||||||
|
Loading…
x
Reference in New Issue
Block a user