On 12/04/2015 03:17 PM, Per Liden wrote:
Hi Peter,
On 2015-12-04 13:35, Peter Levart wrote:
On 12/04/2015 08:16 AM, Per Liden wrote:
test/java/lang/ref/PhantomReferentClearing.java:
85 // Delete root -> O1, collect, verify P1 notified, P2 not
notified.
86 O1 = null;
87 System.gc();
88 if (Q1.remove(ENQUEUE_TIMEOUT) == null) {
89 throw new RuntimeException("P1 not notified by O1
deletion");
90 } else if (Q2.remove(ENQUEUE_TIMEOUT) != null) {
91 throw new RuntimeException("P2 notified by O1
deletion.");
92 }
93
94 // Delete root -> O2, collect. P2 should be notified.
95 O2 = null;
96 System.gc();
97 if (Q2.remove(ENQUEUE_TIMEOUT) == null) {
98 throw new RuntimeException("P2 not notified by O2
deletion");
99 }
The calls to System.gc() isn't guaranteed to do what the test expects
here. As you know, System.gc(), might not actually do anything,
depending on which collector is used and the current circumstances (GC
locker held, a concurrent GC is already in process, etc). To make the
test robust I'd suggest you call System.gc() and check the queue in a
loop, and fail after some reasonable amount of time/iterations.
Whether you poll the queue for some time T or you remove from queue with
timeout of T, it doesn't matter. The Reference(s) are enqueued by a
ReferenceHandler thread and the thread waiting in remove() will get
notified when a reference gets enqueued...
I think you maybe missed my point. There's no guarantee that a call to
System.gc() will cause reference processing to happen at all, and if
it happens there's no guarantee that it will discover P1/P2 here. In
this specific test it's very likely to happen, but that's a different
story. I still don't think this test should rely on a behavior that
isn't guaranteed by the spec.
Ah, you meant to call both System.gc() and queue.poll() in a loop.
Sorry, I haven't understood you at first.
I agree that would be better. Short of System.gc(), is there anything
else that could be used to trigger GC processing more reliably?
What about a loop that allocates until OOME is thrown and then releases
everything so application can recover:
static void triggerGC() {
try {
Object garbage = null;
while(true) {
Object[] chunk = new Object[1<<16];
chunk[0] = garbage;
garbage = chunk;
}
} catch (OutOfMemoryError e) {
// ignore
}
}
I think most GCs guarantee they run the GC before VM throws OOME.
Such test would have to be executed in othrevm with small heap: -Xmx16m
or so...
Regards, Peter
cheers,
/Per
Regards, Peter
cheers,
/Per
http://cr.openjdk.java.net/~kbarrett/8071507/hotspot.05/
Testing:
jprt, aurora ad hoc (defaults, GC/Runtime nightly, JCK)