8257876: Avoid Reference.isEnqueued in tests

Reviewed-by: mchung, tschatzl
This commit is contained in:
Kim Barrett 2020-12-10 10:34:47 +00:00
parent 4a839e95de
commit db5da9619b
3 changed files with 66 additions and 82 deletions

View File

@ -53,6 +53,8 @@ public class ReferencesGC extends ThreadedGCTest {
static int RANGE = 256; static int RANGE = 256;
static float RATIO = (float) 1.0; static float RATIO = (float) 1.0;
static int REMOVE; // Initialized in parseArgs.
static int RETAIN; // Initialized in parseArgs.
public static void main(String[] args) { public static void main(String[] args) {
parseArgs(args); parseArgs(args);
@ -67,6 +69,8 @@ public class ReferencesGC extends ThreadedGCTest {
RATIO = new Float(args[++i]).floatValue(); RATIO = new Float(args[++i]).floatValue();
} }
} }
REMOVE = (int) (RANGE * RATIO);
RETAIN = RANGE - REMOVE;
} }
private class Worker implements Runnable { private class Worker implements Runnable {
@ -76,13 +80,13 @@ public class ReferencesGC extends ThreadedGCTest {
static final int PHANTOM = 2; static final int PHANTOM = 2;
private ExecutionController stresser; private ExecutionController stresser;
int finalizationMaxTime = 1000 * 60 * runParams.getNumberOfThreads(); int finalizationMaxTime = 1000 * 60 * runParams.getNumberOfThreads();
int[] alive = new int[3]; ReferenceQueue refq = null; // Reinitialized each time through loop
int[] enqued = new int[3]; int[] alive = null; // Reinitialized each time through loop
int[] wrong = null; // Reinitialized each time through loop
CircularLinkedList holder[] = new CircularLinkedList[RANGE]; CircularLinkedList holder[] = new CircularLinkedList[RANGE];
WeakReference wr[] = new WeakReference[RANGE]; WeakReference wr[] = new WeakReference[RANGE];
SoftReference sr[] = new SoftReference[RANGE]; SoftReference sr[] = new SoftReference[RANGE];
PhantomReference phr[] = new PhantomReference[RANGE]; PhantomReference phr[] = new PhantomReference[RANGE];
ReferenceQueue refq = new ReferenceQueue();
GarbageProducer gp = GarbageUtils.getArrayProducers().get(0); GarbageProducer gp = GarbageUtils.getArrayProducers().get(0);
int iter = 0; int iter = 0;
@ -93,11 +97,11 @@ public class ReferencesGC extends ThreadedGCTest {
} }
while (stresser.continueExecution()) { while (stresser.continueExecution()) {
int totalQ = 0; int totalLive = 0;
try { try {
refq = new ReferenceQueue(); refq = new ReferenceQueue();
alive = new int[3]; alive = new int[3];
enqued = new int[3]; wrong = new int[3];
for (int j = 0; j < RANGE; j++) { for (int j = 0; j < RANGE; j++) {
holder[j] = new CircularLinkedList(); holder[j] = new CircularLinkedList();
holder[j].addNelements(300); holder[j].addNelements(300);
@ -112,21 +116,21 @@ public class ReferencesGC extends ThreadedGCTest {
} }
for (int i = 0; i < RANGE; i++) { for (int i = 0; i < RANGE; i++) {
if (wr[i].isEnqueued()) { if (wr[i].refersTo(holder[i])) {
++totalQ; ++totalLive;
} }
if (sr[i].isEnqueued()) { if (sr[i].refersTo(holder[i])) {
++totalQ; ++totalLive;
} }
if (phr[i].isEnqueued()) { if (phr[i].refersTo(holder[i])) {
++totalQ; ++totalLive;
} }
} }
if (totalQ != 0) { if (totalLive != 3 * RANGE) {
throw new TestFailure("There are " + totalQ + " references in the queue instead 0 before null-assigment."); throw new TestFailure("There are " + (3 * RANGE - totalLive) + " references cleared before null-assigment.");
} }
for (int i = 0; i < (int) (RANGE * RATIO); i++) { for (int i = 0; i < REMOVE; i++) {
holder[i] = null; holder[i] = null;
} }
@ -137,69 +141,57 @@ public class ReferencesGC extends ThreadedGCTest {
// At this point OOME was thrown and accordingly to spec // At this point OOME was thrown and accordingly to spec
// all weak refs should be processed // all weak refs should be processed
alive = new int[3];
enqued = new int[3];
for (int i = 0; i < RANGE; i++) {
if (wr[i].get() != null) {
++alive[WEAK];
}
if (wr[i].isEnqueued()) {
++enqued[WEAK];
}
if (sr[i].get() != null) {
++alive[SOFT];
}
if (sr[i].isEnqueued()) {
++enqued[SOFT];
}
if (phr[i].isEnqueued()) {
++enqued[PHANTOM];
}
}
long waitTime = System.currentTimeMillis() + finalizationMaxTime; long waitTime = System.currentTimeMillis() + finalizationMaxTime;
while (totalQ < (RANGE * RATIO * 3 * 0.9) && (System.currentTimeMillis() < waitTime)) { int totalQ = 0;
alive = new int[3]; while ((totalQ < (3 * REMOVE)) && (System.currentTimeMillis() < waitTime)) {
enqued = new int[3]; alive[WEAK] = alive[SOFT] = alive[PHANTOM] = 0;
wrong[WEAK] = wrong[SOFT] = wrong[PHANTOM] = 0;
for (int i = 0; i < RANGE; i++) { for (int i = 0; i < RANGE; i++) {
if (wr[i].get() != null) { if (!wr[i].refersTo(holder[i])) {
++wrong[WEAK];
} else if (holder[i] != null) {
++alive[WEAK]; ++alive[WEAK];
} }
if (wr[i].isEnqueued()) {
++enqued[WEAK]; if (!sr[i].refersTo(holder[i])) {
} ++wrong[SOFT];
if (sr[i].get() != null) { } else if (holder[i] != null) {
++alive[SOFT]; ++alive[SOFT];
} }
if (sr[i].isEnqueued()) {
++enqued[SOFT]; if (!phr[i].refersTo(holder[i])) {
} ++wrong[PHANTOM];
if (phr[i].isEnqueued()) { } else if (holder[i] != null) {
++enqued[PHANTOM]; ++alive[PHANTOM];
} }
} }
totalQ = (enqued[WEAK] + enqued[SOFT] + enqued[PHANTOM]);
if (totalQ < (int) (3 * RANGE * RATIO * 0.9)) { try {
log.debug("After null-assignment to " + (int) (RANGE * RATIO) + while (refq.remove(100) != null) {
//" elements from " + lower + " to " + (upper - 1) + ++totalQ;
" and provoking gc found:\n\t" + }
enqued[WEAK] + " weak\n\t" + } catch (InterruptedException ie) {
enqued[SOFT] + " soft\n\t" + }
enqued[PHANTOM] + " phantom " + if (totalQ < (3 * REMOVE)) {
" queuened refs and \n\t" + log.debug("After null-assignment to " + REMOVE +
alive[WEAK] + " weak\n\t" + " referent values and provoking gc found:\n\t" +
alive[SOFT] + " soft\n\t" + totalQ + " queued refs.");
"alive refs.");
try { try {
log.debug("sleeping to give gc one more chance ......"); log.debug("sleeping to give reference processing more time ...");
Thread.sleep(1000); Thread.sleep(1000);
} catch (InterruptedException ie) { } catch (InterruptedException ie) {
} }
} }
} }
log.debug("iteration.... " + iter++); log.debug("iteration.... " + iter++);
if (totalQ < (int) (3 * RANGE * RATIO * 0.9) || totalQ > (int) (3 * RANGE * RATIO)) { if (wrong[WEAK] != 0) {
throw new TestFailure("Test failed"); throw new TestFailure("Expected " + RETAIN + " weak references still alive: " + alive[WEAK]);
} else if (wrong[SOFT] != 0) {
throw new TestFailure("Expected " + RETAIN + " soft references still alive: " + alive[SOFT]);
} else if (wrong[PHANTOM] != 0) {
throw new TestFailure("Expected " + RETAIN + " phantom references still alive: " + alive[PHANTOM]);
} else if (totalQ != (3 * REMOVE)) {
throw new TestFailure("Expected " + (3 * REMOVE) + " references enqueued: " + totalQ);
} }
} }
} }

View File

@ -201,11 +201,12 @@ public class WeakReferenceGC extends ThreadedGCTest {
if (GarbageUtils.eatMemory(getExecutionController()) == 0) { if (GarbageUtils.eatMemory(getExecutionController()) == 0) {
return; // We were unable to provoke OOME before timeout is over return; // We were unable to provoke OOME before timeout is over
} }
numEnqueued = 0; // We set counter to zero to avoid counting references twice try {
for (int i = 0; i < numLists; i++) { while ((numEnqueued < numLists) &&
if (wholder[i].isEnqueued()) { (refQueue.remove(1000) != null)) {
numEnqueued++; numEnqueued++;
} }
} catch (InterruptedException ie) {
} }
} }
results.addElement((new Statistic(iter, numEnqueued))); results.addElement((new Statistic(iter, numEnqueued)));

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2011, 2017, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2011, 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -51,20 +51,17 @@ public class ReferenceEnqueue {
} }
void run() throws InterruptedException { void run() throws InterruptedException {
boolean enqueued = false;
System.gc(); System.gc();
for (int i = 0; i < iterations; i++) { for (int i = 0; i < iterations; i++) {
System.gc(); System.gc();
if (ref.isEnqueued()) { enqueued = (queue.remove(100) == ref);
break; if (enqueued) break;
}
Thread.sleep(100);
} }
if (ref.isEnqueued() == false) { if (!enqueued) {
// GC have not enqueued refWeak for the timeout period // GC have not enqueued refWeak for the timeout period
System.out.println("Reference not enqueued yet"); throw new RuntimeException("Error: reference not enqueued");
return;
} }
if (ref.enqueue() == true) { if (ref.enqueue() == true) {
@ -73,12 +70,6 @@ public class ReferenceEnqueue {
throw new RuntimeException("Error: enqueue() returned true;" throw new RuntimeException("Error: enqueue() returned true;"
+ " expected false"); + " expected false");
} }
if (queue.poll() == null) {
// poll() should return ref enqueued by the GC
throw new RuntimeException("Error: poll() returned null;"
+ " expected ref object");
}
} }
} }
@ -90,7 +81,7 @@ public class ReferenceEnqueue {
ExplicitEnqueue() { ExplicitEnqueue() {
this.refs.add(new SoftReference<>(new Object(), queue)); this.refs.add(new SoftReference<>(new Object(), queue));
this.refs.add(new WeakReference<>(new Object(), queue)); this.refs.add(new WeakReference<>(new Object(), queue));
// Can't test PhantomReference because get() always returns null. this.refs.add(new PhantomReference<>(new Object(), queue));
} }
void run() throws InterruptedException { void run() throws InterruptedException {
@ -98,7 +89,7 @@ public class ReferenceEnqueue {
if (ref.enqueue() == false) { if (ref.enqueue() == false) {
throw new RuntimeException("Error: enqueue failed"); throw new RuntimeException("Error: enqueue failed");
} }
if (ref.get() != null) { if (!ref.refersTo(null)) {
throw new RuntimeException("Error: referent must be cleared"); throw new RuntimeException("Error: referent must be cleared");
} }
} }