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)



Reply via email to