2018-05-17 21:52:47 +00:00
|
|
|
/*
|
2022-05-12 18:38:23 +00:00
|
|
|
* Copyright (c) 2002, 2022, Oracle and/or its affiliates. All rights reserved.
|
2018-05-17 21:52:47 +00:00
|
|
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
|
|
|
*
|
|
|
|
* This code is free software; you can redistribute it and/or modify it
|
|
|
|
* under the terms of the GNU General Public License version 2 only, as
|
|
|
|
* published by the Free Software Foundation.
|
|
|
|
*
|
|
|
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
|
|
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
|
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
|
|
* version 2 for more details (a copy is included in the LICENSE file that
|
|
|
|
* accompanied this code).
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License version
|
|
|
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
|
|
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
|
|
*
|
|
|
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
|
|
|
* or visit www.oracle.com if you need additional information or have any
|
|
|
|
* questions.
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* @test
|
2020-06-09 04:27:22 +00:00
|
|
|
* @key randomness
|
2018-05-17 21:52:47 +00:00
|
|
|
*
|
|
|
|
* @summary converted from VM Testbase gc/gctests/WeakReferenceGC.
|
|
|
|
* VM Testbase keywords: [gc, nonconcurrent]
|
|
|
|
* VM Testbase readme:
|
|
|
|
* *******************************************
|
|
|
|
* set timeout = 25 when running this test
|
|
|
|
* *******************************************
|
|
|
|
* This tests checks to see if the garbage collector enqueues
|
|
|
|
* a weak reference when referrent has been turned to garbage.
|
|
|
|
* Weak references are enqueued in a non-deterministic way
|
|
|
|
* by the garbage collector, so the test uses a heuristic to
|
|
|
|
* determine whether the references are being enqueued in a timely
|
|
|
|
* manner which in turn determines whether outcome of the test.
|
|
|
|
* IF the user invokes the test with the following command line
|
|
|
|
* parameters :
|
|
|
|
* java WeakReferenceGC -qFactor 0.9 -gcCount 5
|
|
|
|
* the test expects that 90% of all objects with only weak references
|
|
|
|
* pointing to them will be enqueued within 5 calls to the garbage collector.
|
|
|
|
* When I ran the test, I consistently got figures of 98% enqueueing
|
|
|
|
* with just 1 call to the garbage collector. So if this test fails,
|
|
|
|
* at its current settings, the garbage collector is not performing as well
|
|
|
|
* as it used to.
|
|
|
|
* The test creates circular linked lists of size 0.1Meg each. The number
|
|
|
|
* of lists created can be set via the -numLists flag. The default
|
|
|
|
* value is 50.
|
|
|
|
* The circular linked lists have both strong and weak references pointing
|
|
|
|
* to them. The strong and weak references are kept in arrays.
|
|
|
|
* The strong references are all nulled out and System.gc() is called
|
|
|
|
* explicitly and the heuristic is applied. If the test does not
|
|
|
|
* satisfy the heuristic or an OutOfMemory exception is thrown,
|
|
|
|
* the test fails.
|
|
|
|
* Array containing Each circular linked list Array containing
|
|
|
|
* weak references is 0.1 Meg each and has strong references
|
|
|
|
* to linked lists. a weak reference, W<n> and a to linked lists.
|
|
|
|
* strong reference, x<n>
|
|
|
|
* pointing to it.
|
|
|
|
* ---- ---------------------------- -----
|
|
|
|
* | | | ---- ---- <-| | |
|
|
|
|
* | W1 |--> -->| |---.......>| | <---- | x1 |
|
|
|
|
* | | -->| |<---.......| |<-- | |
|
|
|
|
* ---- | ---- 1000 --- | -----
|
|
|
|
* ---------------------------
|
|
|
|
* . .
|
|
|
|
* . .
|
|
|
|
* . .
|
|
|
|
* . .
|
|
|
|
* . . 10
|
|
|
|
* . .
|
|
|
|
* ---- ---------------------------- -----
|
|
|
|
* | | | ---- ---- <-| | |
|
|
|
|
* | Wn |--> -->| |---.......>| | <---- | xn |
|
|
|
|
* | | -->| |<---.......| |<-- | |
|
|
|
|
* ---- | ---- 1000 --- | -----
|
|
|
|
* ---------------------------
|
|
|
|
*
|
|
|
|
* @library /vmTestbase
|
|
|
|
* /test/lib
|
2022-05-12 18:38:23 +00:00
|
|
|
* @build jdk.test.whitebox.WhiteBox
|
|
|
|
* @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox
|
2018-05-17 21:52:47 +00:00
|
|
|
* @run main/othervm
|
2022-05-12 18:38:23 +00:00
|
|
|
* -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI
|
2018-05-17 21:52:47 +00:00
|
|
|
* gc.gctests.WeakReferenceGC.WeakReferenceGC
|
|
|
|
* -numList 50
|
|
|
|
* -qFactor 0.9
|
|
|
|
* -gcCount 5
|
|
|
|
* -iter 100
|
|
|
|
*/
|
|
|
|
|
|
|
|
package gc.gctests.WeakReferenceGC;
|
|
|
|
|
|
|
|
import java.util.*;
|
|
|
|
import java.lang.ref.*;
|
2022-05-12 18:38:23 +00:00
|
|
|
|
|
|
|
import jdk.test.whitebox.WhiteBox;
|
2018-05-17 21:52:47 +00:00
|
|
|
import nsk.share.TestFailure;
|
|
|
|
import nsk.share.gc.GC;
|
|
|
|
import nsk.share.gc.ThreadedGCTest;
|
|
|
|
|
|
|
|
public class WeakReferenceGC extends ThreadedGCTest {
|
|
|
|
|
|
|
|
// A heuristic is used to determine the outcome(pass/fail
|
|
|
|
// status) of a test. If 90% of all objects that have
|
|
|
|
// _only_ weak references pointing to them are garbage
|
|
|
|
// collected with 5 explicit calls to the garbage collector
|
|
|
|
// the test is deemed a pass. The following two variables
|
|
|
|
// are used to define this heuristic: gcCount, qFactor
|
|
|
|
|
|
|
|
static String args[];
|
|
|
|
|
|
|
|
CircularLinkedList holder[];
|
|
|
|
|
|
|
|
int loopCount = 100; // # of times test is performed
|
|
|
|
|
|
|
|
int memory_reserve[];
|
|
|
|
int gcCount = 5;
|
|
|
|
int numLists = 50; // number of linked lists
|
|
|
|
float qFactor = (float) 0.9;
|
|
|
|
ReferenceQueue refQueue;
|
|
|
|
Vector results;
|
|
|
|
WeakReference wholder[];
|
|
|
|
|
|
|
|
public static void main(String[] args) {
|
|
|
|
WeakReferenceGC.args = args;
|
|
|
|
GC.runTest(new WeakReferenceGC(), args);
|
|
|
|
}
|
|
|
|
|
|
|
|
WeakReferenceGC() {
|
|
|
|
holder = new CircularLinkedList[numLists];
|
|
|
|
wholder = new WeakReference[numLists];
|
|
|
|
refQueue = new ReferenceQueue();
|
|
|
|
results = new Vector();
|
|
|
|
}
|
|
|
|
|
|
|
|
protected Runnable createRunnable(int i) {
|
|
|
|
return i > 0 ? null : new Worker();
|
|
|
|
}
|
|
|
|
|
|
|
|
private void dumpTestResults() {
|
|
|
|
double objectsRecovered;
|
|
|
|
|
|
|
|
System.out.println("Percentage of Objects" + " # of GC's");
|
|
|
|
System.out.println(" Recovered " + " Required");
|
|
|
|
for (int i = 0; i < results.size(); i++) {
|
|
|
|
Statistic s = (Statistic) results.elementAt(i);
|
|
|
|
objectsRecovered = Math.rint((float) (s.numEnqueued)
|
|
|
|
/ (float) (numLists) * 100.0);
|
|
|
|
System.out.println(" " + objectsRecovered
|
|
|
|
+ " % " + s.iterations);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private boolean hasPassed() {
|
|
|
|
boolean passed;
|
|
|
|
passed = true; // assume passed till proven otherwise
|
|
|
|
|
|
|
|
for (int i = 0; i < results.size(); i++) {
|
|
|
|
Statistic s = (Statistic) results.elementAt(i);
|
|
|
|
if ((s.iterations > gcCount)
|
|
|
|
|| (s.numEnqueued < (int) (numLists * qFactor))) {
|
|
|
|
passed = false;
|
|
|
|
break; // test failed
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return passed;
|
|
|
|
}
|
|
|
|
|
|
|
|
private void parseTestParams(String args[]) {
|
|
|
|
for (int i = 0; i < args.length; i++) {
|
|
|
|
if (args[i].compareTo("-numList") == 0) {
|
2021-02-08 13:19:40 +00:00
|
|
|
numLists = Integer.valueOf(args[++i]).intValue();
|
2018-05-17 21:52:47 +00:00
|
|
|
} else if (args[i].compareTo("-qFactor") == 0) {
|
2021-02-08 13:19:40 +00:00
|
|
|
qFactor = Float.valueOf(args[++i]).floatValue();
|
2018-05-17 21:52:47 +00:00
|
|
|
} else if (args[i].compareTo("-gcCount") == 0) {
|
2021-02-08 13:19:40 +00:00
|
|
|
gcCount = Integer.valueOf(args[++i]).intValue();
|
2018-05-17 21:52:47 +00:00
|
|
|
} else if (args[i].compareTo("-iter") == 0) {
|
2021-02-08 13:19:40 +00:00
|
|
|
loopCount = Integer.valueOf(args[++i]).intValue();
|
2018-05-17 21:52:47 +00:00
|
|
|
// } else {
|
|
|
|
// System.err.println("usage : " +
|
|
|
|
// "java WeakReferenceGC [-numList <n>] " +
|
|
|
|
// "[-qFactor <0.x>] [-gcCount <n>] [-iter <n>]");
|
|
|
|
// throw new TestBug("Invalid arguments");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private void persistentGC() {
|
|
|
|
int numEnqueued, iter, qCriterion;
|
|
|
|
|
|
|
|
numEnqueued = 0; // number of weakReference enqueued
|
|
|
|
iter = 0;
|
|
|
|
qCriterion = (int) (numLists * qFactor);
|
|
|
|
|
|
|
|
while ((numEnqueued < qCriterion) && (iter <= gcCount)) {
|
|
|
|
iter++;
|
|
|
|
if (!getExecutionController().continueExecution()) {
|
|
|
|
return;
|
|
|
|
}
|
2022-05-12 18:38:23 +00:00
|
|
|
WhiteBox.getWhiteBox().fullGC();
|
2020-12-10 10:34:47 +00:00
|
|
|
try {
|
|
|
|
while ((numEnqueued < numLists) &&
|
|
|
|
(refQueue.remove(1000) != null)) {
|
2018-05-17 21:52:47 +00:00
|
|
|
numEnqueued++;
|
|
|
|
}
|
2020-12-10 10:34:47 +00:00
|
|
|
} catch (InterruptedException ie) {
|
2018-05-17 21:52:47 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
results.addElement((new Statistic(iter, numEnqueued)));
|
|
|
|
}
|
|
|
|
|
|
|
|
private void runTest() {
|
|
|
|
int iter;
|
|
|
|
iter = 1;
|
|
|
|
try {
|
|
|
|
do {
|
|
|
|
for (int i = 0; i < numLists; i++) {
|
|
|
|
holder[i] = new CircularLinkedList();
|
|
|
|
holder[i].addNelements(1000);
|
|
|
|
wholder[i] = new WeakReference(holder[i], refQueue);
|
|
|
|
}
|
|
|
|
|
|
|
|
for (int i = 0; i < numLists; i++) {
|
|
|
|
holder[i] = null;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!getExecutionController().continueExecution()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
persistentGC();
|
|
|
|
|
|
|
|
iter++;
|
|
|
|
} while (iter <= loopCount);
|
|
|
|
} catch (OutOfMemoryError e) {
|
|
|
|
memory_reserve = null;
|
|
|
|
System.gc();
|
|
|
|
throw new TestFailure("Failed at iteration=" + loopCount);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//We can't override run() method in WeakReferenceGC, so we are carrying out it to Worker
|
|
|
|
private class Worker implements Runnable {
|
|
|
|
@Override
|
|
|
|
public void run() {
|
|
|
|
parseTestParams(args);
|
|
|
|
runTest();
|
|
|
|
dumpTestResults();
|
|
|
|
boolean passed = hasPassed();
|
|
|
|
if (passed == true) {
|
|
|
|
log.info("Test passed.");
|
|
|
|
} else {
|
|
|
|
log.error("Test failed.");
|
|
|
|
setFailed(true);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
class Statistic {
|
|
|
|
int iterations;
|
|
|
|
int numEnqueued;
|
|
|
|
|
|
|
|
Statistic(int i, int num) {
|
|
|
|
iterations = i;
|
|
|
|
numEnqueued = num;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|