8199257: [TESTBUG] Open source VM testbase metaspace tests

Open sourced VM metaspace tests

Reviewed-by: coleenp, stuefe
This commit is contained in:
Mikhailo Seledtsov 2018-05-22 13:05:22 -07:00
parent 7a898e3e81
commit 6fcf6a9b20
91 changed files with 4827 additions and 1 deletions
test/hotspot/jtreg
ProblemList.txtTEST.groups
vmTestbase/metaspace
flags/maxMetaspaceSize
gc
shrink_grow
CompressedClassSpaceSize
ShrinkGrowMultiJVM
ShrinkGrowTest
staticReferences
stressDictionary
stressHierarchy

@ -123,6 +123,11 @@ vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses023/TestDescrip
vmTestbase/nsk/jdi/EventQueue/remove_l/remove_l005/TestDescription.java 8068225 generic-all
vmTestbase/nsk/jdi/stress/ClassPrepareEvents/ClassPrepareEvents001/ClassPrepareEvents001.java 6426321 generic-all
vmTestbase/metaspace/gc/firstGC_10m/TestDescription.java 8160008 generic-all
vmTestbase/metaspace/gc/firstGC_50m/TestDescription.java 8160008 generic-all
vmTestbase/metaspace/gc/firstGC_99m/TestDescription.java 8160008 generic-all
vmTestbase/metaspace/gc/firstGC_default/TestDescription.java 8160008 generic-all
vmTestbase/gc/lock/jni/jnilock002/TestDescription.java 8191869,8192647 generic-all
vmTestbase/vm/mlvm/indy/func/jdi/breakpointOtherStratum/Test.java 8199578 generic-all

@ -1157,6 +1157,9 @@ vmTestbase_nsk_jdi_quick = \
vmTestbase/nsk/jdi/StackFrame/getArgumentValues/getArgumentValues002/getArgumentValues002.java \
vmTestbase/nsk/jdi/StackFrame/getArgumentValues/getArgumentValues003/getArgumentValues003.java
vmTestbase_vm_metaspace = \
vmTestbase/metaspace
vmTestbase_nsk_stress = \
vmTestbase/nsk/stress
@ -1252,7 +1255,15 @@ vmTestbase_largepages = \
vmTestbase/gc/gctests/LoadUnloadGC \
vmTestbase/gc/gctests/LoadUnloadGC2 \
vmTestbase/gc/memory/LargePagesTest \
vmTestbase/gc/memory/Nio
vmTestbase/gc/memory/Nio \
vmTestbase/metaspace/staticReferences/StaticReferences.java \
vmTestbase/metaspace/stressDictionary/StressDictionary.java \
vmTestbase/metaspace/stressHierarchy/stressHierarchy001/TestDescription.java \
vmTestbase/metaspace/stressHierarchy/stressHierarchy011/TestDescription.java \
vmTestbase/metaspace/flags/maxMetaspaceSize/TestDescription.java \
vmTestbase/metaspace/shrink_grow/ShrinkGrowTest/ShrinkGrowTest.java \
vmTestbase/metaspace/shrink_grow/ShrinkGrowMultiJVM/ShrinkGrowMultiJVM.java \
vmTestbase/metaspace/shrink_grow/CompressedClassSpaceSize/TestDescription.java
# JSR292 tests (invokedynamic AKA Multi-Language VM AKA Da Vinci Machine)
vmTestbase_vm_mlvm = \

@ -0,0 +1,35 @@
/*
* Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved.
* 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
*
* @summary converted from VM Testbase metaspace/flags/maxMetaspaceSize.
*
* @library /vmTestbase /test/lib
* @run driver jdk.test.lib.FileInstaller . .
* @build metaspace.flags.maxMetaspaceSize.maxMetaspaceSize
* @run shell maxMetaspaceSize.sh
*/

@ -0,0 +1,54 @@
/*
* Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
* 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.
*/
/**
* This test set up -XX:MaxMetaspaceSize option and try to to generate OOME
* in metaspace. It also could crash with OOM. This is expected behavior.
*/
package metaspace.flags.maxMetaspaceSize;
import nsk.share.gc.GC;
import nsk.share.gc.GCTestBase;
import nsk.share.gc.gp.*;
import nsk.share.gc.gp.classload.GeneratedClassProducer;
import nsk.share.test.Stresser;
import nsk.share.TestFailure;
public class maxMetaspaceSize extends GCTestBase {
@Override
public void run() {
Stresser stresser = new Stresser(runParams.getStressOptions());
GeneratedClassProducer garbageProducer = new GeneratedClassProducer();
int numOOM = 0;
stresser.start(0);
numOOM = GarbageUtils.eatMemory(stresser, garbageProducer, 50, 100, 2, GarbageUtils.OOM_TYPE.METASPACE);
if ((numOOM == 0) && (stresser.continueExecution())) {
throw new TestFailure("java.lang.OutOfMemoryError: Metadata space. Exception was not thrown.");
} else {
log.info("java.lang.OutOfMemoryError: Metadata space. Was thrown test passed.");
}
}
public static void main (String[] args) {
GC.runTest(new maxMetaspaceSize(), args);
}
}

@ -0,0 +1,45 @@
# Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
# 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.
JAVA="$TESTJAVA/bin/java"
JAVA_OPTS="$TESTJAVAOPTS $TESTVMOPTS -cp $TESTCLASSPATH"
TST="metaspace.flags.maxMetaspaceSize.maxMetaspaceSize"
echo ""
echo "$JAVA $JAVA_OPTS -XX:MaxMetaspaceSize=100m $TST"
echo ""
$JAVA $JAVA_OPTS -XX:MaxMetaspaceSize=100m $TST
res=$?
printf "\n\n"
if [ $res -eq 0 ]; then
echo Test passed
else
grep -s "Out of Memory Error" hs_err_pid*.log
res2=$?
if [ $res2 -eq 0 ]; then
echo JAVA crashed with expected Out of Memory Error error.
echo Test passed
else
echo Test failed
exit 1
fi
fi

@ -0,0 +1,39 @@
/*
* Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
* 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.
*/
package metaspace.gc;
/**
* Exception signaling a test failure.
*/
public class Fault extends RuntimeException {
public Fault(String message) {
super(message);
}
public Fault(Throwable t) {
super(t);
}
}

@ -0,0 +1,230 @@
/*
* Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
* 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.
*/
package metaspace.gc;
import java.io.IOException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import static metaspace.gc.MetaspaceBaseGC.PAGE_SIZE;
/**
* Test for metaspace GC
*
* <ul>
* <li>MetaspaceSize
* </ul>
* Test checks that the first GC happens when metaspace committed is next to
* MetaspaceSize value.
*
* Based on actual events (JDK 8 GC tuning document)
*
* Quating: Java SE 8 HotSpot[tm] Virtual Machine Garbage Collection Tuning
* <pre>
* Class metadata is deallocated when the corresponding Java class is unloaded.
* Java classes are unloaded as a results of garbage collection and garbage
* collections may be induced in order to unload classes and deallocate class
* metadata. When the space used for class metadata reaches a certain level
* (call it a high-water mark), a garbage collection is induced.
*
* The flag MetaspaceSize can be set higher to avoid early garbage collections
* induced for class metadata. The amount of class metadata allocated for
* an application is application dependent and general guidelines do not
* exist for the selection of MetaspaceSize. The default size of MetaspaceSize
* is platform dependent and ranges from 12 MB to about 20 MB.
* </pre>
*/
public class FirstGCTest extends MetaspaceBaseGC {
/**
* Current amount of the used metaspace
*/
protected long used = 0;
/**
* Current amount of the committed metaspace
*/
protected long committed = 0;
/**
* Previous amount of the used metaspace
*/
protected long p_used = 0 ;
/**
* Previous amount of the committed metaspace
*/
protected long p_committed = 0;
public static void main(String... args) {
new FirstGCTest().run(args);
}
// value given in -XX:metaspaceSize=<value>
private long metaspaceSize = -1;
@Override
protected void parseArgs(String[] args) {
final String XXSize = "-XX:MetaspaceSize=";
for (String va: vmArgs) {
if (va.startsWith(XXSize)) {
metaspaceSize = parseValue(va.substring(XXSize.length()));
}
}
}
@Override
protected String getPoolName() {
return "Metaspace";
}
/**
* Check for the first GC moment.
*
* Eats memory until GC is invoked (amount of used metaspace became less);
* Checks that committed memory is close to MemaspaceSize.
* Eats memory until the second GC to check min/max ratio options have effect.
*/
@Override
public void doCheck() {
int gcCount = super.getMetaspaceGCCount();
if (gcCount == 0) {
// gc hasn't happened yet. Start loading classes.
boolean gcHappened = this.eatMemoryUntilGC(50000);
if (!gcHappened) {
throw new Fault("GC hasn't happened");
}
System.out.println("% GC: " + super.lastGCLogLine());
System.out.println("% used : " + p_used + " --> " + used);
System.out.println("% committed: " + p_committed + " --> " + committed);
checkCommitted(p_committed);
} else {
// everything has happened before
checkCommitted(detectCommittedFromGCLog());
}
}
/**
* Check that committed amount is close to expected value (MetaspaceSize)
*
* @param committedAmount - value to check
*/
void checkCommitted(long committedAmount) {
if (metaspaceSize > 0) {
// -XX:MetaspaceSize is given
if (Math.abs((int) (metaspaceSize - committedAmount)) < PAGE_SIZE) {
System.out.println("% GC happened at the right moment");
return;
}
if (!isMetaspaceGC()) {
System.out.println("% GC wasn't induced by metaspace, cannot check the moment :(");
return;
}
System.err.println("%## GC happened at the wrong moment, "
+ "the amount of committed space significantly differs "
+ "from the expected amount");
System.err.println("%## Real : " + committedAmount);
System.err.println("%## Exepcted: " + metaspaceSize);
throw new Fault("GC happened at the wrong moment");
} else {
// -XX:MetaspaceSize is not given, check for default values
if (11_500_000 < committedAmount && committedAmount < 22_500_000) {
System.out.println("% GC happened when the committed amout was from 12 MB to about 20 MB.");
return;
}
if (!isMetaspaceGC()) {
System.out.println("% GC wasn't induced by metaspace, this is excuse");
return;
}
System.err.println("%## GC happened at the wrong moment, "
+ "the amount of committed space was expected from 12 MB to about 20 MB");
System.err.println("%## Real : " + committedAmount);
throw new Fault("It was the wrong moment when GC happened");
}
}
/**
* Load new classes without keeping references to them trying to provoke GC.
* Stops if GC is detected, or number of attempts exceeds the given limit.
*
* @param times limit of attempts to provoke GC
* @return true if GC has happened, false if limit has exceeded.
*/
protected boolean eatMemoryUntilGC(int times) {
System.out.println("%%%% Loading classes");
System.out.println("% iter# : used : commited");
System.out.println("..............................");
for (int i = 1; i < times; i++) {
loadNewClasses(1, false);
if (i % 1000 == 0) {
printMemoryUsage("% " + i + " ");
}
p_used = used;
p_committed = committed;
used = getUsed();
committed = getCommitted();
if (used < p_used) {
return true;
}
}
return false;
}
/**
* If the first full GC has already happened we will try to detect
* the committed amount from the gc.log file.
*
* @return committed amount detected
* @throws Fault if failed to detect.
*/
protected long detectCommittedFromGCLog() {
// parse gc.log to extract the committed value from string like:
// Metaspace used 10133K, capacity 10190K, committed 10240K, reserved 10240Kl
System.out.println("%%%% Parsing gc log to detect the moment of the first GC");
String format = ".*Metaspace.* used .*, capacity .*, committed (\\d+)([KMGkmg]), reserved .*";
Pattern p = Pattern.compile(format);
try {
for (String line: readGCLog()) {
Matcher m = p.matcher(line);
if (m.matches()) {
int amount = Integer.parseInt(m.group(1));
int multi = 1;
switch (m.group(2).toLowerCase()) {
case "k": multi = 1024; break;
case "m": multi = 1024*1024; break;
case "g": multi = 1024*1024*1024; break;
}
long value = amount * multi;
System.out.println("% Committed detected: " + value);
return value;
}
}
} catch (IOException e) {
throw new Fault("Cannot read from the GC log");
}
System.out.println("% String that matches pattern '" + format + "' not found in the GC log file.");
throw new Fault("Unable to detect the moment of GC from log file");
}
}

@ -0,0 +1,242 @@
/*
* Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
* 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.
*/
package metaspace.gc;
import java.util.Arrays;
import vm.share.VMRuntimeEnvUtils;
/**
* Test metaspace ergonomic.
*
* <ul>
* <li>MetaspaceSize
* <li>MaxMetaspaceSize
* <li>MinMetaspaceFreeRatio
* <li>MaxMetaspaceFreeRatio
* </ul>
*
* The test loads classes until the committed metaspace achieves the certain
* level between MetaspaceSize and MaxMetaspaceSize.
* Then it counts how many times GC has been induced.
* Test verifies that MinMetaspaceFreeRatio/MaxMetaspaceFreeRatio settings
* affect the frequency of GC. (High-water mark)
*
* Note: The test doesn't check the GC count if CMS is used.
*
* Quoting: Java SE 8 HotSpot[tm] Virtual Machine Garbage Collection Tuning
* <pre>
* Class metadata is deallocated when the corresponding Java class is unloaded.
* Java classes are unloaded as a results of garbage collection and garbage
* collections may be induced in order to unload classes and deallocate class
* metadata. When the space used for class metadata reaches a certain level
* (call it a high-water mark), a garbage collection is induced.
* After the garbage collection the high-water mark may be raised or lowered
* depending on the amount of space freed from class metadata. The high-water
* mark would be raised so as not to induce another garbage collection too soon.
* The high-water mark is initially set to the value of the command-line
* flag MetaspaceSize . It is raised or lowered based on the flags
* MaxMetaspaceFreeRatio and MinMetaspaceFreeRatio.
* If the committed space available for class metadata as a percentage of
* the total committed space for class metadata is greater than
* MaxMetaspaceFreeRatio, the high-water mark will be lowered.
* If it is less than MinMetaspaceFreeRatio, the high-water mark will be raised.
* </pre>
*/
public class HighWaterMarkTest extends FirstGCTest {
public static void main(String... args) {
new HighWaterMarkTest().run(args);
}
// value given in -XX:MetaspaceSize=<value>
private long metaspaceSize = -1;
// value given in -XX:MaxMetaspaceSize=<value>
private long maxMetaspaceSize = -1;
// value given in -XX:MinMetaspaceFreeRatio=<value>
private long minMetaspaceFreeRatio = -1;
// value given in -XX:MaxMetaspaceFreeRatio=<value>
private long maxMetaspaceFreeRatio = -1;
/**
* Parses arguments and vm options.
* Throws Fault in cases of wrong values or missed parameters.
*
* @param args command line options
*/
@Override
protected void parseArgs(String[] args) {
if (args.length > 0) {
printUsage();
throw new Fault("Illegal arguments: " + Arrays.asList(args));
}
if (gclogFileName == null) {
printUsage();
throw new Fault("Log file name is not given");
}
final String metaSize = "-XX:MetaspaceSize=";
final String maxMetaSize = "-XX:MaxMetaspaceSize=";
final String minRatio = "-XX:MinMetaspaceFreeRatio=";
final String maxRatio = "-XX:MaxMetaspaceFreeRatio=";
for (String va: vmArgs) {
if (va.startsWith(metaSize)) {
metaspaceSize = parseValue(va.substring(metaSize.length()));
} else if (va.startsWith(maxMetaSize)) {
maxMetaspaceSize = parseValue(va.substring(maxMetaSize.length()));
} else if (va.startsWith(minRatio)) {
minMetaspaceFreeRatio = parseValue(va.substring(minRatio.length()));
} else if (va.startsWith(maxRatio)) {
maxMetaspaceFreeRatio = parseValue(va.substring(maxRatio.length()));
}
}
if (metaspaceSize < 0) {
printUsage();
throw new Fault("-XX:MetaspaceSize is not specified");
} else if (maxMetaspaceSize < 0) {
printUsage();
throw new Fault("-XX:MaxMetaspaceSize is not specified");
} else if (minMetaspaceFreeRatio < 0) {
printUsage();
throw new Fault("-XX:MinMetaspaceFreeRatio is not specified");
} else if (maxMetaspaceFreeRatio < 0) {
printUsage();
throw new Fault("-XX:MaxMetaspaceFreeRatio is not specified");
}
}
private void printUsage() {
System.err.println("Usage: ");
System.err.println("java [-Xlog:gc:<filename>] [-XX:MetaspaceSize=..] [-XX:MaxMetaspaceSize=..] [-XX:MinMetaspaceFreeRatio=..] [-XX:MaxMetaspaceFreeRatio=..] \\");
System.err.println(" " + HighWaterMarkTest.class.getCanonicalName());
}
/**
* Check that MinMetaspaceFreeRatio/MaxMetaspaceFreeRatio settings
* affects the moment of the next GC.
*
* Eats memory until amount of committed metaspace achieves a certain level
* (between MetaspaceSize and MaxMetaspaceSize).
* Then checks how many times GC has been invoked.
*
*/
@Override
public void doCheck() {
// to avoid timeouts we limit the number of attempts
int attempts = 0;
int maxAttempts = 10_000;
// in between metaspaceSize and maxMetaspaceSize
// no OOM is exepcted.
long committedLevel = (metaspaceSize + maxMetaspaceSize) / 2;
while (getCommitted() < committedLevel && attempts < maxAttempts) {
attempts++;
loadNewClasses(9, true); // load classes and keep references
loadNewClasses(1, false); // load classes without keeping references
}
System.out.println("% Classes loaded: " + attempts*10);
System.out.println("% Used metaspace : " + bytes2k(getUsed()));
System.out.println("% Committed metaspce: " + bytes2k(getCommitted()));
cleanLoadedClasses();
if (attempts == maxAttempts) {
throw new Fault("Committed amount hasn't achieved " + bytes2k(committedLevel));
}
if (VMRuntimeEnvUtils.isVMOptionEnabled("UseConcMarkSweepGC")) {
System.out.println("ConcMarkSweep is used, cannot count GC");
return;
}
int gcCount = getMetaspaceGCCount();
if (gcCount < 0) {
// perhpas, it's better to silently pass here... Let's see.
throw new Fault ("Unable to count full collections, could be an env issue");
}
System.out.println("% GC has been invoked: " + gcCount + " times");
if (VMRuntimeEnvUtils.isVMOptionEnabled("UseG1GC") &&
VMRuntimeEnvUtils.isVMOptionEnabled("ClassUnloadingWithConcurrentMark")) {
System.out.println("% isG1ClassUnloading: true");
if (gcCount != 0) {
throw new Fault ("G1 should unload classes, full GC is not expected");
}
} else {
if (maxMetaspaceFreeRatio <= 1) {
// min/max = 0/1 boundary value
// GC should happen very often
checkGCCount(gcCount, 20, -1);
} else if (minMetaspaceFreeRatio >= 99) {
// min/max = 99/100 boundary value
// GC should happen very rare
checkGCCount(gcCount, -1, 2);
} else if (minMetaspaceFreeRatio >= 10 && maxMetaspaceFreeRatio <= 20) {
// GC should happen quite often
checkGCCount(gcCount, 3, 30);
} else if (minMetaspaceFreeRatio >= 70 && maxMetaspaceFreeRatio <= 80) {
// GC should happen quite often
checkGCCount(gcCount, 1, 3);
} else {
// hard to estimate
}
}
}
/**
* Checks that count of GC fits the expected range.
* Throws Fault if count is unexpected.
*
* @param count how many times GC has happened
* @param min expected minimum, if under zero - undefined
* @param max expected maximum, if under zero - undefined
*/
void checkGCCount(int count, int min, int max) {
if (min < 0) {
if(count > max) {
throw new Fault("GC has happened too often: " + count + " times, " +
"expected count: less than " + max);
}
} else if (max < 0) {
if(count < min) {
throw new Fault("GC has happened too rare: " + count + " times, " +
"expected count greater than " + min);
}
} else if (count < min || count > max ) {
throw new Fault ("GC has happened " + count + " times, " +
"approximate count is " + min + " to " + max);
}
}
}

@ -0,0 +1,172 @@
/*
* Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
* 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.
*/
package metaspace.gc;
/**
* Test observers the progress on used/committed memory.
* MemoryPoolMXBean is used for that purpose.
*
* Depending on command line option the test checks either Metaspace or
* Compressed Class Space area.
*
* This test checks two things:
* 1) Loading/Unloading classes doesn't cause memory increase
* 2) Loading classes causes permanent increase of memory.
*/
public class MemoryUsageTest extends MetaspaceBaseGC {
private String pool_name;
public static void main(String[] args) {
new MemoryUsageTest().run(args);
}
/**
* Loads new classes by bunches and invokes GC after each bunch.
* Expected behavior: used/committed should stop growing after 5 iterations.
*/
public void checkForNotGrowing() {
long p_used = 0;
long p_committed = 0;
System.out.println("%%%% Loading classes without storing refs, invoking gc manually");
final int numberOfIteration = 10;
for (int i = 0; i < numberOfIteration; i++) {
loadNewClasses(500, false);
gc();
printMemoryUsage("% " + i + " ");
if (i == numberOfIteration / 2) {
// used/committed in the middle of the step.
p_used = getUsed();
p_committed = getCommitted();
}
}
long used = getUsed();
long committed = getCommitted();
// loading classes without keeping references to them
// should not affect used/commited metaspace
// but OK, let's allow some noise such as +/-8K
if (Math.abs((int) (used - p_used)) > 1024*8) {
throw new Fault("Used amount should be stable: " +
p_used + " --> " + used);
}
if (Math.abs((int) (committed - p_committed)) > 1024*8) {
throw new Fault("Committed amount should be stable: " +
p_committed + " --> " + committed);
}
}
/**
* Loads new classes by bunches and invokes GC after each bunch.
* Expected behavior: used/committed should keep growing
*/
public void checkForGrowing() {
long used = 0;
long committed = 0;
long p_used = 0 ;
long p_committed = 0;
// loading new classes, starting to keep references.
// both used and commited metaspace should grow up.
System.out.println("%%%% Loading classes, refs are stored, gc is invoking manually");
for (int i = 0; i < 10; i++) {
try {
loadNewClasses(1000, true);
} catch (OutOfMemoryError oom) {
String message = oom.getMessage().toLowerCase();
if (message.contains("metaspace") || message.contains("compressed class space")) {
System.out.println("% oom is ok: " + oom);
return;
} else {
System.err.println("% unexpected OOM" + oom);
throw new Fault(oom);
}
}
gc();
printMemoryUsage("% " + i + " ");
p_used = used;
p_committed = committed;
used = getUsed();
committed = getCommitted();
if (i > 0 && used <= p_used) {
throw new Fault("Used amount reduced unexpectedly " +
p_used + " --> " + used);
}
if (i > 0 && committed < p_committed) {
throw new Fault("Used amount reduced unexpectedly " +
p_committed + " --> " + committed);
}
}
}
/**
* Looks up for memory pool name.
* @param args command line options
*/
@Override
protected void parseArgs(String[] args) {
if (args.length != 1) {
printUsage();
throw new Fault("MemoryPool is not specified");
}
String a = args[0];
if (a.equalsIgnoreCase("-pool:compressed")) {
pool_name = "Compressed Class Space";
} else if (a.equalsIgnoreCase("-pool:metaspace")) {
pool_name = "Metaspace";
} else {
printUsage();
throw new Fault("Unrecongnized argument: " + a);
}
}
private void printUsage() {
System.err.println("Usage: ");
System.err.println("java [-Xms..] [-XX:MetaspaceSize=..] [-XX:MaxMetaspaceSize=..] \\");
System.err.println(" " + MemoryUsageTest.class.getCanonicalName() + " -pool:<metaspace|compressed>");
}
/**
* @return name of the MemoryPoolMXBean under test
*/
@Override
protected String getPoolName() {
return pool_name;
}
@Override
protected void doCheck() {
checkForNotGrowing();
checkForGrowing();
}
}

@ -0,0 +1,314 @@
/*
* Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
* 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.
*/
package metaspace.gc;
import java.io.IOException;
import java.lang.management.ManagementFactory;
import java.lang.management.MemoryPoolMXBean;
import java.lang.management.MemoryUsage;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.net.URL;
import java.net.URLClassLoader;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import jdk.internal.misc.Unsafe;
/**
* Test that checks how GC works with Metaspace and "Compared Class Space".
*
* It comprises 3 test cases:
* <ul>
* <li>testcase1 - checks that used/committed memory doesn't grow
* when gc is invoked</li>
* <li>testcase2 - checks that gc is invoked when the class metadata u
* sage reaches MetaspaceSize</li>
* <li>testcase3 - checks used/committed grow, inspite of gc is invoked</li>
* </ul>
*
* It's supposed that this class will be executed with various setting of VM
* flags. Via execute args it's possible to say which test cases to run and
* what space to test: Metaspace or Compared Class Space.
*/
public abstract class MetaspaceBaseGC {
// storage of loaded classes
private final Map<String, MetaspaceBaseGC.Foo> loadedClasses = new HashMap<>();
private static int counter = 0;
// pool to test
protected MemoryPoolMXBean pool = null;
// memory page size
protected static final long PAGE_SIZE = detectPageSize();
// true when PAGE_SIZE is large and
protected boolean useLargepages = false;
// where the log will be saved
protected String gclogFileName = null;
protected final Set<String> vmArgs = new HashSet<>();
protected abstract void parseArgs(String args[]);
protected abstract String getPoolName();
protected abstract void doCheck();
public final void run(String args[]) {
configure(args);
if (pool == null) {
System.out.println("%%% Cannot pull the pool, most likely 32-bits only");
return;
}
System.out.println("%%% Working with " + getPoolName());
for (String vmA: vmArgs) {
if (vmA.contains("Metaspace") || vmA.contains("Compressed")) {
System.out.println("% " + vmA);
}
}
doCheck();
System.out.println("% Test passed.");
}
protected void configure(String args[]) {
vmArgs.addAll(ManagementFactory.getRuntimeMXBean().getInputArguments());
useLargepages = PAGE_SIZE > 1_000_000 && !vmArgs.contains("-XX:-UseLargePagesInMetaspace");
System.out.println(vmArgs);
pool = getMemoryPool(getPoolName());
if (pool == null) {
return; // nothing to check
}
for (String arg: vmArgs) {
if (arg.startsWith("-Xlog:gc") && arg.length() > 8) {
gclogFileName = arg.substring(arg.lastIndexOf(':') + 1);
}
}
parseArgs(args);
}
/**
* Imitates class loading.
* Each invocation of this method causes a new class loader object is created
* and a new class is loaded by this class loader.
* Method throws OOM when run out of memory.
*
* @param times how many classes to load
* @param keepRefs true, if references to created classes should be stored
*/
protected void loadNewClasses(int times, boolean keepRefs) {
for (int i = 0; i < times; i++) {
try {
String jarUrl = "file:" + counter + ".jar";
counter++;
URL[] urls = new URL[]{new URL(jarUrl)};
URLClassLoader cl = new URLClassLoader(urls);
MetaspaceBaseGC.Foo foo = (MetaspaceBaseGC.Foo) Proxy.newProxyInstance(cl,
new Class[]{MetaspaceBaseGC.Foo.class},
new MetaspaceBaseGC.FooInvocationHandler(new MetaspaceBaseGC.FooBar()));
if (keepRefs) {
loadedClasses.put(jarUrl, foo);
}
} catch (java.net.MalformedURLException badThing) {
// should never occur
System.err.println("Unexpeted error: " + badThing);
throw new RuntimeException(badThing);
}
}
}
/**
* Cleans references to loaded classes.
*/
protected void cleanLoadedClasses() {
loadedClasses.clear();
}
/**
* Invokes System.gc() and sleeps a little.
*/
protected void gc() {
System.gc();
try {
Thread.currentThread().sleep(500);
} catch (Exception whatever) {
}
}
/**
* Reads gc.log file and returns it as a list of lines.
* It's supposed that the test is executed with -Xlog:gc:gc.log option.
*
* @return List of strings the gc.log file is comprised.
* @throws IOException if problem occurred while reading.
*/
protected List<String> readGCLog() throws IOException {
return Files.readAllLines(Paths.get(".", gclogFileName));
}
/**
* Reads gc.log file and counts GC induced by metaspace.
* Note: this method doesn't work for ConcMarkSweep...
* @return how many times GC induced by metaspace has occurred.
*/
protected int getMetaspaceGCCount() {
int count = 0;
try {
for (String line: readGCLog()) {
if (line.indexOf("Pause Full") > 0 && line.indexOf("Meta") > 0) {
count++;
}
}
return count;
} catch (Throwable t) {
t.printStackTrace(System.err);
return -1;
}
}
protected String lastGCLogLine() {
if (gclogFileName == null) {
return "";
}
try {
List<String> list = Files.readAllLines(Paths.get(".", gclogFileName));
return list.get(list.size() - 1);
} catch (IOException e) {
return "File not found";
}
}
/**
* Does it best to checks if the last GC was caused by metaspace.
*
* This method looks into gc.log file (if -Xloggc:file is given) and returns
* true if the last line in the log contains the "Metadata" word.
* It's not very reliable way to check, log might not be flushed yet.
*
* @return
*/
protected boolean isMetaspaceGC() {
return lastGCLogLine().contains("Metadata");
}
/**
* Prints amounts of used and committed metaspace preceeded by the message
* @param mesg a message to printed prior usages
*/
protected void printMemoryUsage(String mesg) {
MemoryUsage mu = pool.getUsage();
printMemoryUsage(mesg, mu.getUsed(), mu.getCommitted());
}
protected void printMemoryUsage(String mesg, long v1, long v2) {
System.out.println(mesg + ": " + bytes2k(v1) + " : " + bytes2k(v2));
}
protected String bytes2k(long v) {
return (v / 1024) + "k";
}
/**
* @return amount of used memory
*/
public long getUsed() {
return pool.getUsage().getUsed();
}
/**
* @return amount of committed memory
*/
public long getCommitted() {
return pool.getUsage().getCommitted();
}
private static MemoryPoolMXBean getMemoryPool(String name) {
List<MemoryPoolMXBean> pools = ManagementFactory.getMemoryPoolMXBeans();
for (MemoryPoolMXBean pool : pools) {
if (pool.getName().equals(name)) {
return pool;
}
}
return null;
}
private static long detectPageSize() {
try {
Unsafe unsafe = Unsafe.getUnsafe();
int pageSize = unsafe.pageSize();
System.out.println("Page size: " + pageSize);
return pageSize;
} catch (Exception e) {
throw new Fault("Cannot detect page size");
}
}
long parseValue(String s) {
s = s.toLowerCase();
int multiplier = 1;
switch (s.charAt(s.length() - 1)) {
case 'g': multiplier = 1024*1024*1024; break;
case 'm': multiplier = 1024*1024; break;
case 'k': multiplier = 1024; break;
}
if (multiplier == 1) {
return Long.parseLong(s);
} else {
return Long.parseLong(s.substring(0, s.length() - 1)) * multiplier;
}
}
public static interface Foo {
}
public static class FooBar implements Foo {
}
class FooInvocationHandler implements InvocationHandler {
private final Foo foo;
FooInvocationHandler(MetaspaceBaseGC.Foo foo) {
this.foo = foo;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
return method.invoke(foo, args);
}
}
}

@ -0,0 +1 @@
exclusiveAccess.dirs=.

@ -0,0 +1,45 @@
/*
* Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved.
* 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
* @modules java.base/jdk.internal.misc:+open
*
* @summary converted from VM Testbase metaspace/gc/firstGC_10m.
* VM Testbase keywords: [nonconcurrent, quarantine]
* VM Testbase comments: JDK-8160008
*
* @library /vmTestbase /test/lib
* @run driver jdk.test.lib.FileInstaller . .
* @run main/othervm
* -Xms200m
* -Xlog:gc+heap=trace,gc:gc.log
* -XX:MetaspaceSize=10m
* -XX:+IgnoreUnrecognizedVMOptions
* -XX:+UnlockDiagnosticVMOptions
* -XX:-VerifyBeforeExit
* -XX:-UseCompressedOops
* metaspace.gc.FirstGCTest
*/

@ -0,0 +1 @@
exclusiveAccess.dirs=.

@ -0,0 +1,45 @@
/*
* Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved.
* 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
* @modules java.base/jdk.internal.misc:+open
*
* @summary converted from VM Testbase metaspace/gc/firstGC_50m.
* VM Testbase keywords: [nonconcurrent, quarantine]
* VM Testbase comments: JDK-8160008
*
* @library /vmTestbase /test/lib
* @run driver jdk.test.lib.FileInstaller . .
* @run main/othervm
* -Xms200m
* -Xlog:gc+heap=trace,gc:gc.log
* -XX:MetaspaceSize=50m
* -XX:+IgnoreUnrecognizedVMOptions
* -XX:+UnlockDiagnosticVMOptions
* -XX:-VerifyBeforeExit
* -XX:-UseCompressedOops
* metaspace.gc.FirstGCTest
*/

@ -0,0 +1 @@
exclusiveAccess.dirs=.

@ -0,0 +1,45 @@
/*
* Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved.
* 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
* @modules java.base/jdk.internal.misc:+open
*
* @summary converted from VM Testbase metaspace/gc/firstGC_99m.
* VM Testbase keywords: [nonconcurrent, quarantine]
* VM Testbase comments: JDK-8160008
*
* @library /vmTestbase /test/lib
* @run driver jdk.test.lib.FileInstaller . .
* @run main/othervm
* -Xms200m
* -Xlog:gc+heap=trace,gc:gc.log
* -XX:MetaspaceSize=99m
* -XX:+IgnoreUnrecognizedVMOptions
* -XX:+UnlockDiagnosticVMOptions
* -XX:-VerifyBeforeExit
* -XX:-UseCompressedOops
* metaspace.gc.FirstGCTest
*/

@ -0,0 +1 @@
exclusiveAccess.dirs=.

@ -0,0 +1,44 @@
/*
* Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved.
* 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
* @modules java.base/jdk.internal.misc:+open
*
* @summary converted from VM Testbase metaspace/gc/firstGC_default.
* VM Testbase keywords: [nonconcurrent, quarantine]
* VM Testbase comments: JDK-8160008
*
* @library /vmTestbase /test/lib
* @run driver jdk.test.lib.FileInstaller . .
* @run main/othervm
* -Xms200m
* -Xlog:gc+heap=trace,gc:gc.log
* -XX:+IgnoreUnrecognizedVMOptions
* -XX:+UnlockDiagnosticVMOptions
* -XX:-VerifyBeforeExit
* -XX:-UseCompressedOops
* metaspace.gc.FirstGCTest
*/

@ -0,0 +1,42 @@
/*
* Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved.
* 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
* @modules java.base/jdk.internal.misc:+open
*
* @summary converted from VM Testbase metaspace/gc/memoryUsageLargeComp.
* VM Testbase keywords: [nonconcurrent]
*
* @library /vmTestbase /test/lib
* @run driver jdk.test.lib.FileInstaller . .
* @run main/othervm
* -Xms200m
* -XX:MetaspaceSize=100m
* -XX:MinMetaspaceFreeRatio=90
* -XX:MaxMetaspaceFreeRatio=99
* metaspace.gc.MemoryUsageTest
* -pool:compressed
*/

@ -0,0 +1,42 @@
/*
* Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved.
* 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
* @modules java.base/jdk.internal.misc:+open
*
* @summary converted from VM Testbase metaspace/gc/memoryUsageLargeMeta.
* VM Testbase keywords: [nonconcurrent]
*
* @library /vmTestbase /test/lib
* @run driver jdk.test.lib.FileInstaller . .
* @run main/othervm
* -Xms200m
* -XX:MetaspaceSize=100m
* -XX:MinMetaspaceFreeRatio=1
* -XX:MaxMetaspaceFreeRatio=10
* metaspace.gc.MemoryUsageTest
* -pool:metaspace
*/

@ -0,0 +1,41 @@
/*
* Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved.
* 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
* @modules java.base/jdk.internal.misc:+open
*
* @summary converted from VM Testbase metaspace/gc/memoryUsageSmallComp.
* VM Testbase keywords: [nonconcurrent]
*
* @library /vmTestbase /test/lib
* @run driver jdk.test.lib.FileInstaller . .
* @run main/othervm
* -XX:MaxMetaspaceSize=20M
* -XX:MinMetaspaceFreeRatio=10
* -XX:MaxMetaspaceFreeRatio=30
* metaspace.gc.MemoryUsageTest
* -pool:compressed
*/

@ -0,0 +1,41 @@
/*
* Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved.
* 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
* @modules java.base/jdk.internal.misc:+open
*
* @summary converted from VM Testbase metaspace/gc/memoryUsageSmallMeta.
* VM Testbase keywords: [nonconcurrent]
*
* @library /vmTestbase /test/lib
* @run driver jdk.test.lib.FileInstaller . .
* @run main/othervm
* -XX:MetaspaceSize=10M
* -XX:MinMetaspaceFreeRatio=70
* -XX:MaxMetaspaceFreeRatio=90
* metaspace.gc.MemoryUsageTest
* -pool:metaspace
*/

@ -0,0 +1,47 @@
Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
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.
metaspace/gc tests - are the test for the Metaspace GC tuning, which is described in the
Java SE 8 HotSpot[tm] Virtual Machine Garbage Collection Tuning
Tests load classes and monitor the used/committed amounts of metaspace.
There are three types of tests all extending base class - MetaspaceBaseGC
MemoryUsageTest -
trivial test to check memory dynamic (loading classes should lead to growth
of used memory, gc to reduce)
FirstGCTest -
loads classes until the GC has happened and check the GC has happened at the
right moment (as stated in the Spec)
HighWaterMarkTest
The test loads classes until the committed metaspace achieves the certain
level between MetaspaceSize and MaxMetaspaceSize.
Then it counts how many times GC has been induced.
Test verifies that MinMetaspaceFreeRatio/MaxMetaspaceFreeRatio settings
affect the frequency of GC. (High-water mark)
Note: GC could be caused not by Metaspace. When GC happens, the tests check
gc.log file to find the reason of GC. Tests will pass if there is no guarantee
that GC was induced by metaspace.

@ -0,0 +1 @@
exclusiveAccess.dirs=.

@ -0,0 +1,46 @@
/*
* Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved.
* 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
* @modules java.base/jdk.internal.misc:+open
*
* @summary converted from VM Testbase metaspace/gc/watermark_0_1.
* VM Testbase keywords: [nonconcurrent, no_cds]
*
* @library /vmTestbase /test/lib
* @run driver jdk.test.lib.FileInstaller . .
* @run main/othervm
* -Xmx1g
* -Xms150m
* -Xlog:gc:gc.log
* -XX:MetaspaceSize=5m
* -XX:MaxMetaspaceSize=25m
* -XX:MinMetaspaceFreeRatio=0
* -XX:MaxMetaspaceFreeRatio=1
* -XX:+IgnoreUnrecognizedVMOptions
* -XX:-UseCompressedOops
* metaspace.gc.HighWaterMarkTest
*/

@ -0,0 +1 @@
exclusiveAccess.dirs=.

@ -0,0 +1,46 @@
/*
* Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved.
* 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
* @modules java.base/jdk.internal.misc:+open
*
* @summary converted from VM Testbase metaspace/gc/watermark_10_20.
* VM Testbase keywords: [nonconcurrent, no_cds]
*
* @library /vmTestbase /test/lib
* @run driver jdk.test.lib.FileInstaller . .
* @run main/othervm
* -Xmx1g
* -Xms150m
* -Xlog:gc:gc.log
* -XX:MetaspaceSize=5m
* -XX:MaxMetaspaceSize=25m
* -XX:MinMetaspaceFreeRatio=10
* -XX:MaxMetaspaceFreeRatio=20
* -XX:+IgnoreUnrecognizedVMOptions
* -XX:-UseCompressedOops
* metaspace.gc.HighWaterMarkTest
*/

@ -0,0 +1 @@
exclusiveAccess.dirs=.

@ -0,0 +1,46 @@
/*
* Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved.
* 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
* @modules java.base/jdk.internal.misc:+open
*
* @summary converted from VM Testbase metaspace/gc/watermark_70_80.
* VM Testbase keywords: [nonconcurrent, no_cds]
*
* @library /vmTestbase /test/lib
* @run driver jdk.test.lib.FileInstaller . .
* @run main/othervm
* -Xmx1g
* -Xms150m
* -Xlog:gc:gc.log
* -XX:MetaspaceSize=5m
* -XX:MaxMetaspaceSize=25m
* -XX:MinMetaspaceFreeRatio=70
* -XX:MaxMetaspaceFreeRatio=80
* -XX:+IgnoreUnrecognizedVMOptions
* -XX:-UseCompressedOops
* metaspace.gc.HighWaterMarkTest
*/

@ -0,0 +1 @@
exclusiveAccess.dirs=.

@ -0,0 +1,46 @@
/*
* Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved.
* 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
* @modules java.base/jdk.internal.misc:+open
*
* @summary converted from VM Testbase metaspace/gc/watermark_99_100.
* VM Testbase keywords: [nonconcurrent, no_cds]
*
* @library /vmTestbase /test/lib
* @run driver jdk.test.lib.FileInstaller . .
* @run main/othervm
* -Xmx1g
* -Xms150m
* -Xlog:gc:gc.log
* -XX:MetaspaceSize=5m
* -XX:MaxMetaspaceSize=25m
* -XX:MinMetaspaceFreeRatio=99
* -XX:MaxMetaspaceFreeRatio=100
* -XX:+IgnoreUnrecognizedVMOptions
* -XX:-UseCompressedOops
* metaspace.gc.HighWaterMarkTest
*/

@ -0,0 +1,41 @@
/*
* Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved.
* 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
*
* @summary converted from VM Testbase metaspace/shrink_grow/CompressedClassSpaceSize.
* VM Testbase keywords: [monitoring, quarantine]
* VM Testbase comments: JDK-8058967
*
* @library /vmTestbase /test/lib
* @run driver jdk.test.lib.FileInstaller . .
* @run main/othervm
* -DrequiresCompressedClassSpace=true
* -XX:MaxMetaspaceSize=100m
* -XX:CompressedClassSpaceSize=10m
* -Xlog:gc*:gc.log
* metaspace.shrink_grow.ShrinkGrowTest.ShrinkGrowTest
*/

@ -0,0 +1,129 @@
/*
* Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
* 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
*
* @summary converted from VM Testbase metaspace/shrink_grow/ShrinkGrowMultiJVM.
* VM Testbase keywords: [nonconcurrent]
*
* @library /vmTestbase /test/lib
* @run driver jdk.test.lib.FileInstaller . .
* @build metaspace.shrink_grow.ShrinkGrowMultiJVM.ShrinkGrowMultiJVM
* @run driver metaspace.shrink_grow.ShrinkGrowMultiJVM.ShrinkGrowMultiJVM
*/
package metaspace.shrink_grow.ShrinkGrowMultiJVM;
import jdk.test.lib.Utils;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
/**
* This test starts several JVMs and run ShrinkGrow metaspace test.
*
* It expected that all the parameters on start new processes are given
* in the command line.
*/
public class ShrinkGrowMultiJVM {
private static final String[] TEST_ARGS = {
Paths.get(Utils.TEST_JDK)
.resolve("bin")
.resolve("java")
.toAbsolutePath()
.toString(),
"-Xlog:gc:gc_$i.log", // LOG_GC_ARG_INDEX
"-XX:MetaspaceSize=10m",
"-XX:MaxMetaspaceSize=20m",
"-cp",
Utils.TEST_CLASS_PATH
};
private static final int LOG_GC_ARG_INDEX = 1;
public static void main(String argv[]) {
String[] testJavaOpts = Utils.getTestJavaOpts();
String[] args = new String[TEST_ARGS.length + testJavaOpts.length + 2];
System.arraycopy(TEST_ARGS, 0, args, 0, TEST_ARGS.length);
System.arraycopy(testJavaOpts, 0, args, TEST_ARGS.length, testJavaOpts.length);
args[args.length - 2] = metaspace.shrink_grow.ShrinkGrowTest.ShrinkGrowTest.class.getCanonicalName();
args[args.length - 1] = "jvm#$i";
for (int i = 0; i < args.length; ++i) {
System.out.println("%arg #" + i + ": " + args[i]);
}
List<Process> list = new ArrayList<>();
for (int i = 0; i < 5; i++) {
// will be used as jvm id
args[args.length - 1] = "jvm#" + i;
args[LOG_GC_ARG_INDEX] = "-Xlog:gc:gc_" + i + ".log";
ProcessBuilder pb = new ProcessBuilder(args);
try {
Process p = pb.start();
// Redirect.INHERIT doesn't work w/ @run driver
new Thread(() -> copy(p.getInputStream(), System.out)).start();
new Thread(() -> copy(p.getErrorStream(), System.out)).start();
list.add(p);
System.out.println("=== process #" + i + " started");
} catch (IOException e) {
throw new Error("Failed to start process " + i, e);
}
}
int failedCount = 0;
for (int i = 0; i < list.size(); i++) {
Process p = list.get(i);
try {
int exitCode = p.waitFor();
if (exitCode != 0) {
failedCount++;
System.out.println("=== process #" + i + " exitCode=" + exitCode);
}
} catch (InterruptedException e) {
failedCount++;
System.out.println("=== process #" + i + " waitFor failed");
e.printStackTrace(System.out);
}
}
if (failedCount != 0) {
throw new AssertionError(failedCount + " out of " + list.size() + " tests failed");
}
}
private static void copy(InputStream is, OutputStream os) {
byte[] buffer = new byte[1024];
int n;
try (InputStream close = is) {
while ((n = is.read(buffer)) != -1) {
os.write(buffer, 0, n);
}
os.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
}

@ -0,0 +1,284 @@
/*
* Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
* 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
*
* @summary converted from VM Testbase metaspace/shrink_grow/ShrinkGrowTest.
*
* @library /vmTestbase /test/lib
* @run driver jdk.test.lib.FileInstaller . .
* @run main/othervm
* -XX:MetaspaceSize=10m
* -XX:MaxMetaspaceSize=20m
* -Xlog:gc*:gc.log
* metaspace.shrink_grow.ShrinkGrowTest.ShrinkGrowTest
*/
package metaspace.shrink_grow.ShrinkGrowTest;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.management.ManagementFactory;
import java.lang.management.MemoryPoolMXBean;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.HashMap;
import java.util.Map;
/**
* This is the main test in the metaspace shrink/grow series.
*
* It tries to allocate all available metespace (loads new classes and keeps
* them in map), then checks that loading new classes causes OOM.
* After that it does cleanup loaded classes and then expect the new classes
* could be loaded again.
*
* <b>Note</b>: Don't forget to limit the metaspace size by giving
* -XX:MaxMetaspaceSize=100k vm option.
*/
public class ShrinkGrowTest {
/**
* Dead classes storage.
*/
private final Map<String, ShrinkGrowTest.Foo> loadedClasses = new HashMap<>();
private static int counter = 0;
private String errorMessage = "not completed";
// thread id to distinguish threads in output
private final String whoAmI;
// the limit of classes to load expecting OOM
private final int maxClassesToLoad;
public static void main(String[] args) {
String name = args.length > 0 ? args[0] : "singleTest" ;
new ShrinkGrowTest(name, 20000).run();
}
/**
* @param name - thread id used in logging
* @param classesToLoad - the limit of classes to load expecting OOM
*/
public ShrinkGrowTest(String name, int classesToLoad) {
whoAmI = name;
maxClassesToLoad = classesToLoad;
}
/**
* Just outputs given message preceeded with the thread identifier
*
* @param message text to print out
*/
void log(String message) {
System.out.println("%" + whoAmI + "% " + message);
}
void throwFault(String message) {
throw new TestFault("%" + whoAmI + "% " + message);
}
void throwFault(String message, Throwable t) {
throw new TestFault("%" + whoAmI + "% " + message, t);
}
/**
* Entry to the test.
* Just exits if passes or throws an Error if failed.
*/
public void run() {
if (System.getProperty("requiresCompressedClassSpace") != null &&
!isCompressedClassSpaceAvailable()) {
System.out.println("Not applicalbe, Compressed Class Space is required");
return;
}
try {
log("Bootstrapping string concatenation for " + whoAmI );
go();
// The quest completed! Yahoo!
setErrorMessage(null);
log("passed");
} catch (TestFault failure) {
failure.printStackTrace(System.err);
setErrorMessage(failure.getMessage());
log("failed :" + errorMessage);
throw failure;
} catch (Throwable badThing) {
setErrorMessage(badThing.toString());
throw new TestFault(badThing);
}
}
private void go() {
// step 1: eat all metaspace
log("eating metaspace");
runOutOfMetaspace(maxClassesToLoad);
// step 2: try to load one more class
// it should be impossible
try {
eatALittleMemory();
throwFault("We haven't cleaned metaspace yet!");
} catch (OutOfMemoryError error) {
if (!isMetaspaceError(error)) {
throwFault("Hmm, we ran out metaspace. Metaspace error is still excpected here " + error, error);
}
}
// step 3: clean up metaspace and try loading a class again.
log("washing hands before meal");
loadedClasses.clear();
System.gc();
try {
log("one more try to eat");
eatALittleMemory();
} catch (OutOfMemoryError error) {
throwFault("we already should be able to consume metaspace " + error, error);
}
}
/**
* @return true if the test has successfully passed.
*/
public boolean isPassed() {
return errorMessage == null;
}
/**
* @return message describing the reason of failure, or null if passes
*/
public String getErrorMessage() {
return errorMessage;
}
/**
* Sets the message describing why test failed, or null if test passed
*/
void setErrorMessage(String msg) {
errorMessage = msg;
}
/**
* Loads new classes until OOM.
* Checks that OOM is caused by metaspace and throws an Error if not.
*
* @param times - maximum limit of classes to load.
*/
private void runOutOfMetaspace(int times) {
try {
for (int i = 0; i < times; i++) {
eatALittleMemory();
}
} catch (OutOfMemoryError error) {
if (isMetaspaceError(error)) {
return;
}
throwFault("We ran out of another space, not metaspace: " + error, error);
}
throwFault("OOM hasn't happened after " + times + " iterations. Might be too much space?..");
}
/**
* Imitates class loading.
* Each invocation of this method causes a new class loader object is created
* and a new class is loaded by this class loader.
* Method throws OOM when run out of memory.
*/
private void eatALittleMemory() {
try {
String jarUrl = "file:" + counter + ".jar";
counter++;
URL[] urls = new URL[]{new URL(jarUrl)};
URLClassLoader cl = new URLClassLoader(urls);
ShrinkGrowTest.Foo foo = (ShrinkGrowTest.Foo) Proxy.newProxyInstance(cl,
new Class[]{ShrinkGrowTest.Foo.class},
new ShrinkGrowTest.FooInvocationHandler(new ShrinkGrowTest.FooBar()));
loadedClasses.put(jarUrl, foo);
} catch (java.net.MalformedURLException badThing) {
// should never occur
throwFault("Unexpeted error: " + badThing, badThing);
}
}
/**
* Checks if given OOM is about metaspace
* @param error OOM
* @return true if message contains 'metaspace' word, false otherwise.
*/
boolean isMetaspaceError(OutOfMemoryError error) {
String message = error.getMessage();
return message != null && (message.contains("Metaspace") ||
message.contains("Compressed class space"));
}
boolean isCompressedClassSpaceAvailable() {
for (MemoryPoolMXBean pool : ManagementFactory.getMemoryPoolMXBeans()) {
if (pool.getName().equalsIgnoreCase("Compressed class space")) {
return true;
}
}
return false;
}
/**
* Runtime exception signaling test failure.
*/
public static class TestFault extends RuntimeException {
public TestFault(String message) {
super(message);
}
public TestFault(Throwable t) {
super(t);
}
public TestFault(String message, Throwable t) {
super(message, t);
}
}
public static interface Foo {
}
public static class FooBar implements ShrinkGrowTest.Foo {
}
class FooInvocationHandler implements InvocationHandler {
private final ShrinkGrowTest.Foo foo;
FooInvocationHandler(ShrinkGrowTest.Foo foo) {
this.foo = foo;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
return method.invoke(foo, args);
}
}
}

@ -0,0 +1,32 @@
/*
* Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
* 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.
*/
package metaspace.staticReferences;
public class OneUsageClassloader extends ClassLoader {
public Class<?> define(byte[] bytecode) {
return defineClass(null, bytecode, 0 ,bytecode.length);
}
}

@ -0,0 +1,265 @@
/*
* Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
* 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
* @modules java.base/jdk.internal.misc:+open
*
* @summary converted from VM Testbase metaspace/staticReferences.
* VM Testbase keywords: [nonconcurrent, javac, no_cds]
*
* @library /vmTestbase /test/lib
* @run driver jdk.test.lib.FileInstaller . .
* @build sun.hotspot.WhiteBox
* @run driver ClassFileInstaller sun.hotspot.WhiteBox
* sun.hotspot.WhiteBox$WhiteBoxPermission
* @run main/othervm
* -Xmx800m
* -Xbootclasspath/a:.
* -XX:+UnlockDiagnosticVMOptions
* -XX:+WhiteBoxAPI
* metaspace.staticReferences.StaticReferences
*/
package metaspace.staticReferences;
import java.lang.ref.WeakReference;
import java.lang.ref.Reference;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Random;
import vm.share.InMemoryJavaCompiler;
import nsk.share.gc.GCTestBase;
import nsk.share.test.ExecutionController;
import nsk.share.test.Stresser;
import nsk.share.test.TestBase;
import nsk.share.test.Tests;
import jdk.internal.misc.Unsafe;
import vm.share.gc.TriggerUnloadingHelper;
import vm.share.gc.TriggerUnloadingWithWhiteBox;
/**
* Test checks that static fields will be initialized in new loaded class. Test performs in loop the following routine:
* 1.) Load class either by regular classloader or by Unsafe.defineAnonymousClass.
* 2.) Trigger unloading. Class must be alive. Next step will check that static fields would not lost.
* 3.) Change static fields.
* 4.) Unload class.
* 5.) Load class again as in step 1.
* 6.) Check that static fields were initialized.
*/
@SuppressWarnings("rawtypes")
public class StaticReferences extends GCTestBase {
private static final int UNLOADING_ATTEMPTS_LIMIT = 50;
private static final Object[] NO_CP_PATCHES = new Object[0];
private static String[] args;
private static final int LIMIT = 100;
private List<Object> keepAlive = new LinkedList<Object>();
private Random random;
private TriggerUnloadingHelper triggerUnloadingHelper = new TriggerUnloadingWithWhiteBox();
private String[] typesArray = new String[] {"Object object", "boolean boolean", "byte byte", "char char", "double double", "float float", "int int", "long long", "short short"};
public static void main(String[] args) {
StaticReferences.args = args;
Tests.runTest(new StaticReferences(), args);
}
private static Unsafe getUnsafe() {
return Unsafe.getUnsafe();
}
@Override
public void run() {
random = new Random(runParams.getSeed());
ExecutionController stresser = new Stresser(args);
stresser.start(1);
// Generate and compile classes
List<byte[]> bytecodeList = new LinkedList<byte[]>();
int[] fieldQuantities = new int[9];
long startTimeStamp = System.currentTimeMillis();
for (int i = 0; i < LIMIT; i++) {
if (!stresser.continueExecution()) {
return;
}
for (int j = 0; j < fieldQuantities.length; j++) {
fieldQuantities[j] = 1 + random.nextInt(2000);
}
bytecodeList.add(generateAndCompile(fieldQuantities));
}
log.info("Compilation finished in " + ((System.currentTimeMillis() - startTimeStamp)/1000/60.0) + " minutes ");
// Core of test
for (byte[] classBytecode : bytecodeList) {
boolean anonymous = random.nextBoolean();
log.info("Load class first time");
Class clazz = loadClass(classBytecode, anonymous);
log.info("Trigger unloading");
triggerUnloadingHelper.triggerUnloading(stresser);
if (!stresser.continueExecution()) {
return;
}
log.info("Set up static fields. This will check that static fields are reachable.");
setupFields(clazz);
log.info("Cleanup references");
Reference<Class> weakReference = new WeakReference<Class>(clazz);
clazz = null;
log.info("Trigger unloading again");
int numberOfAttemps = 0;
while (weakReference.get() != null && numberOfAttemps < UNLOADING_ATTEMPTS_LIMIT) {
if (!stresser.continueExecution()) {
return;
}
triggerUnloadingHelper.triggerUnloading(stresser);
}
if (numberOfAttemps >= UNLOADING_ATTEMPTS_LIMIT) {
setFailed(true);
throw new RuntimeException("Test failed: was unable to unload class with " + UNLOADING_ATTEMPTS_LIMIT + " attempts.");
}
log.info("Load class second time");
clazz = loadClass(classBytecode, anonymous);
log.info("check fields reinitialized");
checkStaticFields(clazz);
keepAlive.add(clazz);
}
}
private Class loadClass(byte[] classBytecode,
boolean anonymous) {
Class clazz;
if (anonymous) {
clazz = getUnsafe().defineAnonymousClass(StaticReferences.class, classBytecode, NO_CP_PATCHES);
} else {
OneUsageClassloader classloader = new OneUsageClassloader();
clazz = classloader.define(classBytecode);
}
return clazz;
}
private void checkStaticFields(Class clazz) {
for (Field field : clazz.getFields()) {
try {
if (Modifier.isStatic(field.getModifiers())) {
Class fieldType = field.getType();
if ((fieldType.equals(Object.class) && field.get(null) != null )
|| (fieldType.equals(int.class) && field.getInt(null) != 0)
|| (fieldType.equals(boolean.class) && field.getBoolean(null) != false)
|| (fieldType.equals(char.class) && field.getChar(null) != 0)
|| (fieldType.equals(long.class) && field.getLong(null) != 0)
|| (fieldType.equals(short.class) && field.getShort(null) != 0)
|| (fieldType.equals(float.class) && field.getFloat(null) != 0.0f)
|| (fieldType.equals(double.class) && field.getDouble(null) != 0.0)
|| (fieldType.equals(byte.class) && field.getByte(null) != 0)) {
setFailed(true);
throw new RuntimeException("Failing test: field "
+ field.getName() + " of type "
+ field.getType() + " in class "
+ field.getDeclaringClass().getName()
+ " was not cleared");
}
}
} catch (IllegalArgumentException | IllegalAccessException e) {
e.printStackTrace();
throw new RuntimeException("Was unable to set static field "
+ field.getName() + " of type "
+ field.getType().getName() + " in class "
+ field.getDeclaringClass().getName(), e);
}
}
}
private byte[] generateAndCompile(int[] filedQuantities) {
Map<String, CharSequence> sources = new HashMap<String, CharSequence>();
sources.put("A", generateSource(filedQuantities));
return InMemoryJavaCompiler.compile(sources).values().iterator().next();
}
private StringBuffer generateSource(int[] fieldQuantities) {
StringBuffer result = new StringBuffer("public class A { \n");
int fieldsCounter = 0;
for (int i = 0; i < typesArray.length; i++) {
for (int j = 0; j < fieldQuantities[i]; j++) {
result.append(" public static " + typesArray[i] + fieldsCounter++ + ";\n");
}
}
result.append(" } ");
return result;
}
private void setupFields(Class clazz) {
for (Field field : clazz.getFields()) {
try {
if (Modifier.isStatic(field.getModifiers())) {
Class fieldType = field.getType();
if (fieldType.equals(Object.class)) {
field.set(null, this);
} else if (fieldType.equals(int.class)) {
field.setInt(null, 42);
} else if (fieldType.equals(boolean.class)) {
field.setBoolean(null, true);
} else if (fieldType.equals(char.class)) {
field.setChar(null, 'c');
} else if (fieldType.equals(long.class)) {
field.setLong(null, (long) 42);
} else if (fieldType.equals(short.class)) {
field.setShort(null, (short) 42);
} else if (fieldType.equals(float.class)) {
field.setFloat(null, 42.42f);
} else if (fieldType.equals(double.class)) {
field.setDouble(null, 42.42);
} else if (fieldType.equals(byte.class)) {
field.setByte(null, (byte) 42);
}
}
} catch (IllegalArgumentException | IllegalAccessException e) {
e.printStackTrace();
throw new RuntimeException(
"Was unable to set static field " + field.getName()
+ " of type " + field.getType().getName()
+ " in class "
+ field.getDeclaringClass().getName(), e);
}
}
}
}

@ -0,0 +1 @@
exclusiveAccess.dirs=.

@ -0,0 +1,38 @@
/*
* Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
* 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.
*/
package metaspace.stressDictionary;
public class ClassloaderUnderTest extends ClassLoader {
private static boolean isParallelCapable;
public static boolean isParallelCapableCL() { return isParallelCapable; }
{
isParallelCapable = registerAsParallelCapable();
}
public Class<?> define(byte[] bytecode) {
return defineClass(null, bytecode, 0 ,bytecode.length);
}
}

@ -0,0 +1,173 @@
/*
* Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
* 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
*
* @summary converted from VM Testbase metaspace/stressDictionary.
* VM Testbase keywords: [nonconcurrent, javac]
*
* @library /vmTestbase /test/lib
* @run driver jdk.test.lib.FileInstaller . .
* @run main/othervm metaspace.stressDictionary.StressDictionary
*/
package metaspace.stressDictionary;
import java.util.*;
import java.lang.management.ManagementFactory;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicLong;
import nsk.share.gc.GCTestBase;
import nsk.share.test.*;
import vm.share.InMemoryJavaCompiler;
/**
* There is a data structure named "dictionary" in class BlockFreelist. It stores
* information about free memory blocks for further reusing. Allocation of new block goes
* from dictionary only if dictionary is fat enough. (At the moment of test creation this limit is 64K.)
* So to stress dictionary we should fill it permanently. The easiest way to fill the dictionary
* is to fail class loading. This failed action will return allocated blocks to dictionary.
*
* There are two type of threads in this test: threads, failing classloading and threads,
* loading regular classes and checking they work properly.
*/
public class StressDictionary extends GCTestBase {
private class FillingDictionaryWorker implements Callable<Object> {
@Override
public Object call() throws Exception {
while (stresser.continueExecution()) {
try {
byte[] bytecode = generateAndCompile();
bytecode[random.nextInt(bytecode.length)] = (byte) 42;
classloader.define(bytecode);
changeClassloaderIfRequired();
} catch (Throwable e) {
// We can get ClassFormatError, ClassNotFoundException or anything else here
}
}
return null;
}
}
private class RegularWorker implements Callable<Object> {
@Override
public Object call() throws Exception {
while (stresser.continueExecution()) {
byte[] bytecode = generateAndCompile();
Class<?> c = classloader.define(bytecode);
testClass(c);
changeClassloaderIfRequired();
}
return null;
}
}
private static String[] args;
private static final int DROP_CLASSLOADER_LIMIT = 50000;
private static final String methodName = "myMethod";
private static final int NUMBER_OF_CORRUPTING_THREADS = 10;
private static final int NUMBER_OF_METHOD_CALLS = 50;
private static final int NUMBER_OF_NOT_CORRUPTING_THREADS = 10;
private AtomicLong classesCounter = new AtomicLong(0);
private volatile ClassloaderUnderTest classloader = new ClassloaderUnderTest();
private Random random;
private ExecutionController stresser;
public static void main(String[] args) {
StressDictionary.args = args;
Tests.runTest(new StressDictionary(), args);
}
public void run() {
random = new Random(runParams.getSeed());
stresser = new Stresser(args);
stresser.start(1);
List<Callable<Object>> tasks = new LinkedList<Callable<Object>>();
for (int i = 0; i < NUMBER_OF_CORRUPTING_THREADS; i++) {
tasks.add(this.new FillingDictionaryWorker());
}
for (int i = 0; i < NUMBER_OF_NOT_CORRUPTING_THREADS; i++) {
tasks.add(this.new RegularWorker());
}
ExecutorService executorService = Executors.newCachedThreadPool();
try {
executorService.invokeAll(tasks);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
private void changeClassloaderIfRequired() {
if (ManagementFactory.getClassLoadingMXBean().getLoadedClassCount() > DROP_CLASSLOADER_LIMIT) {
ClassloaderUnderTest newOne = new ClassloaderUnderTest();
classloader = newOne;
}
}
private byte[] generateAndCompile() {
Map<String, CharSequence> sources = new HashMap<String, CharSequence>();
String className = "MyClass" + classesCounter.incrementAndGet();
sources.put(className, generateSource(className));
return InMemoryJavaCompiler.compile(sources).values().iterator().next();
}
private CharSequence generateSource(String className) {
return "public class " + className + " { " +
"public static String s1 = \"s1" + random.nextInt() + "\"; " +
"public String s2 = \"s2" + random.nextInt() + "\"; " +
"public String " + methodName + "() {return s1 + s2; } " +
"}";
}
private void testClass(Class<?> clazz) {
try {
for (Method m : clazz.getMethods()) {
if (m.getName().equals(methodName)) {
for (int j = 0; j < NUMBER_OF_METHOD_CALLS; j++) {
m.invoke(clazz.newInstance());
}
}
}
} catch (InstantiationException | IllegalAccessException | InvocationTargetException e) {
log.error("Class check failed: " + e.getMessage());
e.printStackTrace();
setFailed(true);
}
}
}

@ -0,0 +1 @@
exclusiveAccess.dirs=.

@ -0,0 +1,84 @@
/*
* Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved.
* 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.
*/
package metaspace.stressHierarchy.common;
import jdk.test.lib.JDKToolLauncher;
import jdk.test.lib.Utils;
import jdk.test.lib.process.ProcessTools;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.stream.Stream;
public class GenClassesBuilder {
public static void main(String[] args) {
Path srcDst = Paths.get("genSrc").toAbsolutePath();
Path classesDir = Paths.get(Utils.TEST_CLASSES).toAbsolutePath();
generateSource(srcDst);
compileSource(srcDst, classesDir);
}
private static void compileSource(Path srcDst, Path classesDir) {
JDKToolLauncher javac = JDKToolLauncher.create("javac")
.addToolArg("-d")
.addToolArg(classesDir.toString())
.addToolArg("-cp")
.addToolArg(Utils.TEST_CLASS_PATH);
try (Stream<Path> stream = Files.walk(srcDst)) {
stream.map(Path::toAbsolutePath)
.map(Path::toString)
.filter(s -> s.endsWith(".java"))
.forEach(javac::addToolArg);
} catch (IOException e) {
throw new Error("traverse source dir " + srcDst, e);
}
String[] command = javac.getCommand();
try {
ProcessTools.executeCommand(command)
.shouldHaveExitValue(0);
} catch (Error | RuntimeException e) {
throw e;
} catch (Throwable e) {
throw new Error("execution of javac(" + Arrays.toString(command) + ") failed", e);
}
}
private static void generateSource(Path dir) {
try {
Files.createDirectories(dir);
} catch (IOException e) {
throw new Error("can't create dirs for" + dir, e);
}
try {
HumongousClassGen.main(new String[]{dir.toString()});
} catch (Exception e) {
throw new Error("can't generate classes", e);
}
}
}

@ -0,0 +1,91 @@
/*
* Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
* 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.
*/
package metaspace.stressHierarchy.common;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
/**
* This class is compiled and invoke due the build to produce
* HumongousClass.java. The size of generated file is
* too large to store it in the repository.
*/
public class HumongousClassGen {
private static final String CLASS_NAME = "HumongousClass";
private static final String PKG_NAME = "metaspace.stressHierarchy.common";
private static final String PKG_DIR_NAME = PKG_NAME.replace(".",
File.separator);
private static final int ITERATIONS = 65300;
private static final double MG = (Math.pow(1024, 2));
private static final int RECORD_COUNT = ITERATIONS + 10;
public static void addFileHeader(List<String> records) {
records.add("package " + PKG_NAME + ";\n");
records.add("\n");
records.add("public class " + CLASS_NAME + " {\n");
records.add("\n");
}
public static void main(String[] args) throws Exception {
if (args.length < 1) {
System.out.println("Usage: HumongousClassGen "
+ "<vm-testbase_src_folder>");
throw new RuntimeException("Can't generate " + PKG_NAME + "." + CLASS_NAME);
}
List<String> records = new ArrayList<String>(RECORD_COUNT);
addFileHeader(records);
for (int i = 1; i <= ITERATIONS; i++) {
records.add("public long long" + i + ";\n");
}
records.add("}");
writeBuffered(records, (int) (MG * 1), args[0]);
}
private static void writeBuffered(List<String> records, int bufSize,
String srcDir) throws IOException {
String path = srcDir + File.separator + PKG_DIR_NAME + File.separator
+ CLASS_NAME + ".java";
System.out.println("Path="+path);
File file = new File (path);
file.getParentFile().mkdirs();
file.createNewFile();
long start = System.currentTimeMillis();
FileWriter writer = new FileWriter(file);
BufferedWriter bufferedWriter = new BufferedWriter(writer, bufSize);
for (String record: records) {
bufferedWriter.write(record);
}
bufferedWriter.flush();
bufferedWriter.close();
long end = System.currentTimeMillis();
System.out.println((end - start) / 1000f + " seconds");
}
}

@ -0,0 +1,205 @@
/*
* Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
* 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.
*/
package metaspace.stressHierarchy.common;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.List;
import metaspace.stressHierarchy.common.classloader.tree.Node;
import metaspace.stressHierarchy.common.classloader.tree.Tree;
import metaspace.stressHierarchy.common.exceptions.ClassNotUnloadedException;
import metaspace.stressHierarchy.common.exceptions.TimeIsOverException;
import nsk.share.test.ExecutionController;
import sun.hotspot.WhiteBox;
import vm.share.gc.TriggerUnloadingHelper;
public class PerformChecksHelper {
private static final int NUMBER_OF_HOT_METHOD_CALLS = 100;
private static WhiteBox wb = WhiteBox.getWhiteBox();
// This is the number of failed attempts required to deem class unloading failed
private int attemptsLimit = 50;
// This is the pause between unloading attempts in milliseconds
private long unloadingPause = 1000;
// This is the number of failed attempts after that pauses will be involved
private int pausesLimit = 5;
private TriggerUnloadingHelper triggerUnloadingHelper = null;
private ExecutionController stresser;
public PerformChecksHelper(TriggerUnloadingHelper triggerUnloadingHelper, int attemptsLimit, long unloadingPause, int pausesLimit) {
this.triggerUnloadingHelper = triggerUnloadingHelper;
if (attemptsLimit != -1) {
this.attemptsLimit = attemptsLimit;
}
if (unloadingPause != -1) {
this.unloadingPause = unloadingPause;
}
if (pausesLimit != -1) {
this.pausesLimit = pausesLimit;
}
System.out.println("attemptsLimit = " + this.attemptsLimit);
System.out.println("unloadingPause = " + this.unloadingPause);
System.out.println("pausesLimit = " + this.pausesLimit);
}
public void checkLevelReclaimed(Tree tree, int level)
throws IllegalAccessException, InvocationTargetException, InstantiationException, ClassNotUnloadedException, TimeIsOverException {
long attempsCounter = 0;
boolean checkPassed = false;
ClassNotUnloadedException classNotUnloadedException = null;
while (!checkPassed && attempsCounter++ < attemptsLimit) {
if (attempsCounter > pausesLimit && unloadingPause > 0) {
try {
Thread.sleep(unloadingPause);
} catch (InterruptedException e) {
throw new RuntimeException("Somebody dared to interrupt thread while we were waiting after gc provoke");
}
}
try {
checkLevel(tree, level, false);
checkPassed = true;
} catch (ClassNotUnloadedException exception) {
checkPassed = false;
classNotUnloadedException = exception;
triggerUnloadingHelper.triggerUnloading(stresser);
}
}
if (!checkPassed) {
System.out.println("Going to throw classNotUnloadedException. attempsCounter = " + attempsCounter);
throw classNotUnloadedException;
}
}
public void checkLevelAlive(Tree tree, int level) throws IllegalAccessException, InvocationTargetException, InstantiationException, ClassNotUnloadedException, TimeIsOverException {
checkLevel(tree, level, true);
}
private void checkLevel(Tree tree, int level, boolean shouldBeAlive)
throws IllegalAccessException, InvocationTargetException, InstantiationException, ClassNotUnloadedException, TimeIsOverException {
for (Node node : tree.getNodesInLevel(level)) {
for (String className : node.getLoadedClassesNames()) {
checkStresser();
boolean isClassAlive = wb.isClassAlive(className);
if (isClassAlive != shouldBeAlive) {
throw new ClassNotUnloadedException("Failing test! Class: " + className + " shouldBeAlive: " + shouldBeAlive
+ " isClassAlive: " + isClassAlive);
}
}
}
if (shouldBeAlive) {
checkAncestorsAlive(tree, level);
}
}
private void callMethods(Class<?> clazz)
throws IllegalAccessException, IllegalArgumentException,
InvocationTargetException, InstantiationException {
try {
for (Method m : clazz.getMethods()) {
for (int j = 0; j < NUMBER_OF_HOT_METHOD_CALLS; j++) {
if (m.getName().equals("composeString")) {
m.invoke(clazz.newInstance());
} else if (m.getName().equals("calculate")) {
m.invoke(clazz.newInstance());
} else if (m.getName().equals("calculate2")) {
m.invoke(clazz.newInstance());
}
}
}
} catch (OutOfMemoryError e) {
if (e.getMessage().trim().toLowerCase().contains("metadata")) {
System.out.println("Got OOME in metaspace in PerformChecksHelper.callMethods(Class clazz). " +
"This happened because reflection generates a too many accessors. " +
"There is nothing we can do with it, so we are just suppressing.");
} else {
throw e;
}
}
}
private void checkAncestors(Class<?> clazz) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, InstantiationException, TimeIsOverException {
for (; clazz != null; clazz = clazz.getSuperclass()) {
checkStresser();
if (!clazz.isInterface()) {
//check class
callMethods(clazz);
} else {
//check interface by implementing it
InvocationHandler handler = new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
return Integer.MIN_VALUE;
}
};
Object instance = Proxy.newProxyInstance(clazz.getClassLoader(), new Class[] {clazz}, handler);
instance.hashCode();
}
if (!wb.isClassAlive(clazz.getName())) {
throw new RuntimeException("Test failed in method checkAncestors: class "
+ clazz.getName() + " should be alive");
}
}
}
private void checkAncestorsAlive(Tree tree, int level)
throws IllegalAccessException, InvocationTargetException,
InstantiationException, IllegalArgumentException, TimeIsOverException {
List<Node> bottomLevel = tree.getNodesInLevel(level);
if (bottomLevel.isEmpty()) {
throw new RuntimeException("Failing test because of test bug: no nodes in bottom level");
}
for (Node node : bottomLevel) {
if (node.getLoadedClasses() == null || node.getLoadedClasses().isEmpty()) {
throw new RuntimeException("Failing test because of test bug: no classes loaded by node " + node);
}
for (Class<?> clazz : node.getLoadedClasses()) {
checkAncestors(clazz);
}
}
}
public void setStresser(ExecutionController stresser) {
this.stresser = stresser;
}
private void checkStresser() throws TimeIsOverException {
if (stresser == null) {
throw new RuntimeException("Test bug. Wrong usage of PerformChecksHelper. Stresser was not set.");
}
if (!stresser.continueExecution()) {
throw new TimeIsOverException();
}
}
}

@ -0,0 +1,64 @@
/*
* Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
* 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.
*/
package metaspace.stressHierarchy.common;
import nsk.share.test.ExecutionController;
import nsk.share.test.Tests;
import metaspace.stressHierarchy.common.classloader.tree.Tree;
/**
* Test checks that ancestors will not be reclaimed while references on descenders are alive.
* We create hierarchy of classes, each loaded by dedicated classloader. Then we cleanup
* references to all nodes except those that are in bottom level. Finally we check that classes
* in bottom level are alive.
*/
public class StressHierarchy1 extends StressHierarchyBaseClass {
public static void main(String[] args) {
try {
StressHierarchyBaseClass.args = args;
Tests.runTest(new StressHierarchy1(), args);
} catch (OutOfMemoryError error) {
System.out.print("Got OOME: " + error.getMessage());
}
}
@Override
protected void runTestLogic(Tree tree, ExecutionController stresser)
throws Throwable {
for (int cleanupLevel = tree.getMaxLevel() - 1; cleanupLevel > 1; cleanupLevel--) {
tree.cleanupLevel(cleanupLevel);
log.info("cleanupLevel=" + cleanupLevel);
triggerUnloadingHelper.triggerUnloading(stresser);
if (!stresser.continueExecution()) {
// pass test
return;
}
}
log.info("Check bottom level");
performChecksHelper.checkLevelAlive(tree, tree.getMaxLevel());
}
}

@ -0,0 +1,76 @@
/*
* Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
* 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.
*/
package metaspace.stressHierarchy.common;
import metaspace.stressHierarchy.common.classloader.tree.Tree;
import metaspace.stressHierarchy.common.exceptions.ClassNotUnloadedException;
import nsk.share.test.ExecutionController;
import nsk.share.test.Tests;
/**
* Test case checks that presence of ancestors does not prevent descenders of being reclaimed.
* We create hierarchy of classes, each loaded by dedicated classloader. Then we start the following
* routine in loop: release references to classes in bottom level, provoke unloading and check
* 1) that classes in bottom level were unloaded and
* 2) that next to bottom level was NOT unloaded.
*/
public class StressHierarchy2 extends StressHierarchyBaseClass {
public static void main(String[] args) {
try {
StressHierarchyBaseClass.args = args;
Tests.runTest(new StressHierarchy2(), args);
} catch (OutOfMemoryError error) {
System.out.print("Got OOME: " + error.getMessage());
}
}
@Override
protected void runTestLogic(Tree tree, ExecutionController stresser)
throws Throwable {
for (int cleanupLevel = tree.getMaxLevel(); cleanupLevel >= 0; cleanupLevel-- ) {
tree.cleanupLevel(cleanupLevel);
log.info("cleanupLevel=" + cleanupLevel);
triggerUnloadingHelper.triggerUnloading(stresser);
if (!stresser.continueExecution()) {
return;
}
if (cleanupLevel > 0) {
performChecksHelper.checkLevelAlive(tree, cleanupLevel - 1);
}
if (!stresser.continueExecution()) {
return;
}
try {
performChecksHelper.checkLevelReclaimed(tree, cleanupLevel);
} catch (ClassNotUnloadedException exception) {
log.error("Class was not unloaded." + exception.toString());
setFailed(true);
throw exception;
}
}
}
}

@ -0,0 +1,72 @@
/*
* Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
* 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.
*/
package metaspace.stressHierarchy.common;
import metaspace.stressHierarchy.common.classloader.tree.Tree;
import nsk.share.test.ExecutionController;
import nsk.share.test.Tests;
/**
* 1. Test case cleans up all levels except bottom, then checks that bottom level is alive (and whole tree).
* 2. Then test cleans up whole tree and checks that it is reclaimed.
*/
public class StressHierarchy3 extends StressHierarchyBaseClass {
public static void main(String[] args) {
try {
StressHierarchyBaseClass.args = args;
Tests.runTest(new StressHierarchy3(), args);
} catch (OutOfMemoryError error) {
System.out.print("Got OOME: " + error.getMessage());
}
}
@Override
protected void runTestLogic(Tree tree, ExecutionController stresser)
throws Throwable {
for (int cleanupLevel = tree.getMaxLevel() - 1; cleanupLevel >= 0; cleanupLevel--) {
if (! stresser.continueExecution()) { return; }
tree.cleanupLevel(cleanupLevel);
log.info("cleanupLevel=" + cleanupLevel);
}
triggerUnloadingHelper.triggerUnloading(stresser);
if (! stresser.continueExecution()) { return; }
log.info("Check bottom level alive ");
performChecksHelper.checkLevelAlive(tree, tree.getMaxLevel());
if (! stresser.continueExecution()) { return; }
log.info("Cleanup all");
tree.cleanupLevel(tree.getMaxLevel());
triggerUnloadingHelper.triggerUnloading(stresser);
log.info("Check bottom level reclaimed");
performChecksHelper.checkLevelReclaimed(tree, tree.getMaxLevel());
}
}

@ -0,0 +1,156 @@
/*
* Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
* 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.
*/
package metaspace.stressHierarchy.common;
import java.net.MalformedURLException;
import vm.share.gc.TriggerUnloadingByFillingMetaspace;
import vm.share.gc.TriggerUnloadingHelper;
import vm.share.gc.TriggerUnloadingWithWhiteBox;
import metaspace.stressHierarchy.common.classloader.tree.Node;
import metaspace.stressHierarchy.common.classloader.tree.Tree;
import metaspace.stressHierarchy.common.exceptions.GotWrongOOMEException;
import metaspace.stressHierarchy.common.exceptions.TimeIsOverException;
import metaspace.stressHierarchy.common.generateHierarchy.GenerateHierarchyHelper;
import metaspace.stressHierarchy.common.generateHierarchy.GenerateHierarchyHelper.Type;
import metaspace.stressHierarchy.common.generateHierarchy.NodeDescriptor;
import metaspace.stressHierarchy.common.generateHierarchy.TreeDescriptor;
import nsk.share.test.ExecutionController;
import nsk.share.test.Stresser;
import nsk.share.test.TestBase;
import nsk.share.test.timeoutwatchdog.TimeoutHandler;
import nsk.share.test.timeoutwatchdog.TimeoutWatchdog;
/**
* Superclass for StressHierarchy* tests. It provides util methods to create and load
* classes hierarchy and perform checks.
*/
abstract public class StressHierarchyBaseClass extends TestBase implements TimeoutHandler {
protected static String[] args;
protected TriggerUnloadingHelper triggerUnloadingHelper = new TriggerUnloadingWithWhiteBox(); //default helper
protected PerformChecksHelper performChecksHelper = null;
private int treeDepth;
private int minLevelSize;
private int maxLevelSize;
private Type hierarchyType;
public void run() {
try {
int attemptsLimit = -1; // -1 means using default value defined in PerformChecksHelper
long unloadingPause = -1; // -1 means the same
int pausesLimit = -1; // -1 means the same
for (int ind = 0; ind < args.length; ind++ ) {
if ("-triggerUnloadingByFillingMetaspace".equals(args[ind])) {
log.info("using TriggerUnloadingByFillingMetaspace");
triggerUnloadingHelper = new TriggerUnloadingByFillingMetaspace();
} else if ("-treeDepth".equals(args[ind])) {
this.treeDepth = Integer.parseInt(args[ind + 1]);
} else if ("-minLevelSize".equals(args[ind])) {
this.minLevelSize = Integer.parseInt(args[ind + 1]);
} else if ("-maxLevelSize".equals(args[ind])) {
this.maxLevelSize = Integer.parseInt(args[ind + 1]);
} else if ("-attemptsLimit".equals(args[ind])) {
attemptsLimit = Integer.valueOf(args[ind + 1]);
} else if ("-unloadingPause".equals(args[ind])) {
unloadingPause = Long.valueOf(args[ind + 1]);
} else if ("-pausesLimit".equals(args[ind])) {
pausesLimit = Integer.valueOf(args[ind + 1]);
} else if ("-hierarchyType".equals(args[ind])) {
String s = args[ind + 1];
hierarchyType = Type.CLASSES.toString().equals(s) ? Type.CLASSES :
(Type.INTERFACES.toString().equals(s) ? Type.INTERFACES : Type.MIXED);
System.out.println("hierarchyType = " + hierarchyType);
} else if (args[ind].startsWith("-") && !args[ind].equals("-stressTime")) {
throw new RuntimeException("Unknown option " + args[ind]);
}
}
performChecksHelper = new PerformChecksHelper(triggerUnloadingHelper, attemptsLimit, unloadingPause, pausesLimit);
log.info("treeDepth=" + treeDepth + ", minLevelSize=" + minLevelSize + ", maxLevelSize=" + maxLevelSize + ", hierarchyType=" + hierarchyType +
", triggerUnloadingHelper.getClass().getName()=" + triggerUnloadingHelper.getClass().getName());
long startTimeStamp = System.currentTimeMillis();
ExecutionController stresser = new Stresser(args);
stresser.start(1);
TimeoutWatchdog.watch(stresser, this);
TreeDescriptor treeDescriptor = GenerateHierarchyHelper.generateHierarchy(treeDepth, minLevelSize, maxLevelSize, hierarchyType);
Tree tree = buildTree(treeDescriptor);
System.out.println("Generating took " + ((System.currentTimeMillis() - startTimeStamp)/1000) +" sec");
performChecksHelper.setStresser(stresser);
runTestLogic(tree, stresser);
System.out.println("Whole test took " + ((System.currentTimeMillis() - startTimeStamp)/1000/60.0) +" min");
log.info("Test PASSED");
} catch (GotWrongOOMEException e) {
log.info("GotWrongOOMEExc: " + e.getMessage());
log.info("Got wrong type of OOME. We are passing test as it breaks test logic. We have dedicated test configurations" +
" for each OOME type provoking class unloading, that's why we are not missing test coverage here.");
} catch (OutOfMemoryError e) {
log.info("Got OOME.");
} catch (TimeIsOverException e) {
log.info("Time is over. That's okay. Passing test");
} catch (Throwable throwable) {
//Throw runtime exception. nsk framework will catch it, log and set appropriate exit code
log.error("Test failed. Exception catched.");
throwable.printStackTrace();
throw new RuntimeException(throwable);
}
}
@Override
public void handleTimeout() {
System.out.println("Shutting down vm because of time expired.");
System.exit(95);
}
abstract protected void runTestLogic(Tree tree, ExecutionController stresser) throws Throwable;
private Tree buildTree(TreeDescriptor treeDescriptor) throws MalformedURLException,
ClassNotFoundException, InstantiationException,
IllegalAccessException {
log.info("Create tree");
Tree tree = new Tree();
for (NodeDescriptor nodeDescriptor : treeDescriptor.nodeDescriptorList) {
tree.addNode(nodeDescriptor);
}
log.info("Load classes and instantiate objects");
for (Node node : tree.getNodes()) {
node.loadClasses();
node.instantiateObjects();
}
return tree;
}
}

@ -0,0 +1,88 @@
/*
* Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
* 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.
*/
package metaspace.stressHierarchy.common.classloader;
import java.net.URLClassLoader;
import java.net.URL;
import java.util.HashSet;
import java.util.Set;
import metaspace.stressHierarchy.common.generateHierarchy.NodeDescriptor;
/**
* This classloader tries to load each class itself before forwarding to parent.
* Also it stores loaded classes and class names.
*
*/
public class StressClassloader extends URLClassLoader {
private final Set<Class<?>> loadedClasses = new HashSet<Class<?>>();
private final Set<String> loadedClassesNames = new HashSet<String>();
private String className;
private byte[] bytecode;
public StressClassloader(NodeDescriptor nodeDescriptor,
StressClassloader parentClassLoader) {
super(new URL[] {}, parentClassLoader);
this.className = nodeDescriptor.className;
this.bytecode = nodeDescriptor.bytecode;
}
public Set<Class<?>> getLoadedClasses() {
return loadedClasses;
}
public Set<String> getLoadedClassNames() {
return loadedClassesNames;
}
@Override
public Class<?> loadClass(String name) throws ClassNotFoundException {
if (loadedClassesNames.contains(name)) {
throw new RuntimeException("Classloader " + toString() + " loads class " + name + " second time! ");
}
Class<?> alreadyLoaded = findLoadedClass(name);
if (alreadyLoaded != null) {
return alreadyLoaded;
}
if (className.equals(name)) {
Class<?> clazz = defineClass(name, bytecode, 0, bytecode.length);
loadedClasses.add(clazz);
loadedClassesNames.add(clazz.getName());
return clazz;
} else {
return super.loadClass(name);
}
}
@Override
public String toString() {
return "StressClassloader@" + className;
}
}

@ -0,0 +1,134 @@
/*
* Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
* 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.
*/
package metaspace.stressHierarchy.common.classloader.tree;
import java.util.HashSet;
import java.util.Set;
import metaspace.stressHierarchy.common.classloader.StressClassloader;
/**
* Node of tree
*
*/
public class Node {
private int level;
private Set<String> loadedClassesNames;
private int number;
private Set<Object> objects = new HashSet<Object>();
private Node parent = null;
private StressClassloader classloader;
public Node(int level, int number) {
this.level = level;
this.number = number;
}
public void cleanup() {
loadedClassesNames = getClassLoader().getLoadedClassNames();
objects.clear();
getClassLoader().getLoadedClasses().clear();
classloader = null;
}
@Override
public boolean equals(Object obj) {
if (obj instanceof Node) {
Node other = (Node) obj;
return other.getLevel() == level && other.getNumber() == number;
} else {
return false;
}
}
StressClassloader getClassLoader() { //package access level
return classloader;
}
public int getLevel() {
return level;
}
public Set<Class<?>> getLoadedClasses() {
return getClassLoader() == null ? null : getClassLoader().getLoadedClasses();
}
public Set<String> getLoadedClassesNames() {
if (loadedClassesNames != null) {
return loadedClassesNames;
} else if (getClassLoader() != null) {
return getClassLoader().getLoadedClassNames();
}
return null;
}
public int getNumber() {
return number;
}
public Node getParent() {
return parent;
}
@Override
public int hashCode() {
return level + number * 999;
}
public void instantiateObjects() throws InstantiationException, IllegalAccessException {
for (Class<?> c : getClassLoader().getLoadedClasses()) {
if (!c.isInterface()) {
objects.add(c.newInstance());
}
}
}
public boolean isRoot() {
return (parent == null);
}
public void setClassLoader(StressClassloader classLoader) {
classloader = classLoader;
}
public void setParent(Node parent) {
this.parent = parent;
}
@Override
public String toString() {
return "Node@level=" + level + "_num=" + number;
}
public void loadClasses() throws ClassNotFoundException {
String className = "package_level" + getLevel() + "_num" + getNumber() + ".Dummy";
getClassLoader().loadClass(className);
}
}

@ -0,0 +1,99 @@
/*
* Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
* 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.
*/
package metaspace.stressHierarchy.common.classloader.tree;
import java.util.*;
import metaspace.stressHierarchy.common.classloader.StressClassloader;
import metaspace.stressHierarchy.common.generateHierarchy.NodeDescriptor;
/**
* Tree of hierarchy.
*
* The tree consists of {@link Nodes}s. Each node contains classloader {@link metaspace.stressHierarchy.common.classloader.StressClassloader} that is
* associated with one class (or interface) and can load only it. Edge in this
* tree correspond to parent relation between corresponding classloaders.
* Each classloader delegates to parent only after failed attempt to load class itself.
*
*/
public class Tree {
private final List<Node> allNodes = new LinkedList<Node>(); //order matters
private int maxLevel;
private Node root;
public void cleanupLevel(int level) {
for (Node node : getNodesInLevel(level)) {
node.cleanup();
}
}
public int getMaxLevel() { return maxLevel; }
public List<Node> getNodes() {
return allNodes;
}
public List<Node> getNodesInLevel(int level) {
List<Node> result = new LinkedList<Node>();
for (Iterator<Node> iter = allNodes.iterator(); iter.hasNext();) {
Node current = iter.next();
if (current.getLevel() == level) {
result.add(current);
}
}
return result;
}
private Node findParent(Node node) {
for (Iterator<Node> iter = allNodes.iterator(); iter.hasNext();) {
Node current = iter.next();
if (current.equals(node)) {
return current;
}
}
return null;
}
public void addNode(NodeDescriptor nodeDescriptor) {
if (nodeDescriptor.level == 0) {
root = new Node(0, 0);
root.setClassLoader(new StressClassloader(nodeDescriptor, null));
allNodes.add(root);
return;
}
Node newOne = new Node(nodeDescriptor.level, nodeDescriptor.index);
Node parent = findParent(new Node(nodeDescriptor.level - 1, nodeDescriptor.parentIndex));
//add a payload to new node
newOne.setClassLoader(new StressClassloader(nodeDescriptor, parent.getClassLoader()));
newOne.setParent(parent);
allNodes.add(newOne);
maxLevel = maxLevel < newOne.getLevel() ? newOne.getLevel() : maxLevel;
}
}

@ -0,0 +1,33 @@
/*
* Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
* 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.
*/
package metaspace.stressHierarchy.common.exceptions;
public class ClassNotUnloadedException extends Exception {
public ClassNotUnloadedException(String string) {
super(string);
}
private static final long serialVersionUID = 1L;
}

@ -0,0 +1,38 @@
/*
* Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
* 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.
*/
package metaspace.stressHierarchy.common.exceptions;
/**
* Usually this means that we got OOME:heap while trying to gain OOME:metaspace.
* We pass test in this case as this breaks test logic. We have dedicated test configurations
* for OOME:heap provoking class unloading, that why we are not missing test coverage here.
*/
public class GotWrongOOMEException extends RuntimeException {
private static final long serialVersionUID = 1L;
public GotWrongOOMEException(String string) {
super(string);
}
}

@ -0,0 +1,29 @@
/*
* Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
* 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.
*/
package metaspace.stressHierarchy.common.exceptions;
public class TimeIsOverException extends Exception {
private static final long serialVersionUID = 1L;
}

@ -0,0 +1,135 @@
/*
* Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
* 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.
*/
package metaspace.stressHierarchy.common.generateHierarchy;
import java.util.*;
import vm.share.InMemoryJavaCompiler;
public class GenerateHierarchyHelper {
public static enum Type {
CLASSES, INTERFACES, MIXED;
}
// Class-container that represents generated source file
private static class ClassDescriptor {public String fullName; public CharSequence sourceCode; }
private static enum Inheritance {
CLASS_EXTENDS_CLASS, CLASS_IMPLEMENTS_INTERFACE, INTERFACE_EXTENDS_INTERFACE
}
private static final int EDGE_IN_MIXED_CASE = 30;
private static Random random = new Random();
public static TreeDescriptor generateHierarchy(int depth, int minLevelSize, int maxLevelSize, Type type) {
TreeDescriptor tree = new TreeDescriptor();
Map<String, CharSequence> sourceMap = new HashMap<String, CharSequence>();
int numberOfNodesInPrevLevel = 1;
// generate root
String packageName = composePackageName(0, 0);
String className = packageName + ".Dummy";
switch (type) {
case CLASSES:
sourceMap.put(className, "package " + packageName +";\n public class Dummy { " +
"public int calculate2() {return hashCode();} " +
"public double calculate() {return hashCode() + 0.1;} " +
"public String composeString() {return \"_root_\";}" +
"}");
break;
default:
sourceMap.put(className, "package " + packageName + ";\n public interface Dummy {}");
}
tree.addNode(0, 0, 0, className);
for (int level = 1; level < depth; level++) {
int nodesInLevel = minLevelSize + random.nextInt(maxLevelSize - minLevelSize);
for (int nodeIndex = 0; nodeIndex < nodesInLevel; nodeIndex++) {
int parent = random.nextInt(numberOfNodesInPrevLevel);
Inheritance inheritance = null;
switch (type) {
case CLASSES:
inheritance = Inheritance.CLASS_EXTENDS_CLASS;
break;
case INTERFACES:
inheritance = Inheritance.INTERFACE_EXTENDS_INTERFACE;
break;
case MIXED:
inheritance = level < EDGE_IN_MIXED_CASE ? Inheritance.INTERFACE_EXTENDS_INTERFACE
: (level == EDGE_IN_MIXED_CASE ? Inheritance.CLASS_IMPLEMENTS_INTERFACE
: Inheritance.CLASS_EXTENDS_CLASS);
break;
}
ClassDescriptor classDescriptor = generateClassCode(level, nodeIndex, parent, inheritance);
sourceMap.put(classDescriptor.fullName, classDescriptor.sourceCode);
tree.addNode(level, nodeIndex, parent, classDescriptor.fullName);
}
numberOfNodesInPrevLevel = nodesInLevel;
}
Map<String, byte[]> bytecodeMap = InMemoryJavaCompiler.compile(sourceMap);
for (NodeDescriptor nodeDescriptor : tree.nodeDescriptorList) {
nodeDescriptor.bytecode = bytecodeMap.get(nodeDescriptor.className);
}
return tree;
}
private static String composePackageName(int level, int nodeIndex) {
return "package_level" + level + "_num" + nodeIndex;
}
private static ClassDescriptor generateClassCode(int level, int nodeIndex, int parent, Inheritance inheritance) {
ClassDescriptor result = new ClassDescriptor();
String packageName = composePackageName(level, nodeIndex);
String parentPackage = composePackageName(level - 1, parent);
result.fullName = packageName + ".Dummy";
StringBuffer source = new StringBuffer("package ");
source.append(packageName + ";\n\n");
switch (inheritance) {
case INTERFACE_EXTENDS_INTERFACE:
source.append(" public interface Dummy extends " + parentPackage + ".Dummy {}");
break;
case CLASS_EXTENDS_CLASS:
source.append(" public class Dummy extends " + parentPackage + ".Dummy { " +
"public int calculate2() {return (super.calculate2() + hashCode() % 1000);} " +
"public double calculate() {return (super.calculate() + hashCode() + 0.1);} " +
"public String composeString() {return super.composeString() + \"_" + packageName + "_\";}" +
"}");
break;
case CLASS_IMPLEMENTS_INTERFACE:
source.append(" public class Dummy implements " + parentPackage + ".Dummy { " +
"public int calculate2() {return hashCode();} " +
"public double calculate() {return hashCode() + 0.1;} " +
"public String composeString() {return \"_ancestor_class_\";}" +
"}");
break;
}
result.sourceCode = source;
return result;
}
}

@ -0,0 +1,37 @@
/*
* Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
* 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.
*/
package metaspace.stressHierarchy.common.generateHierarchy;
public class NodeDescriptor {
public String className;
public byte[] bytecode;
public int level;
public int index;
public int parentIndex;
}

@ -0,0 +1,41 @@
/*
* Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
* 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.
*/
package metaspace.stressHierarchy.common.generateHierarchy;
import java.util.LinkedList;
import java.util.List;
public class TreeDescriptor {
public List<NodeDescriptor> nodeDescriptorList = new LinkedList<NodeDescriptor>();
public void addNode(int level, int index, int parentIndex, String className) {
NodeDescriptor node = new NodeDescriptor();
node.className = className;
node.level = level;
node.index = index;
node.parentIndex = parentIndex;
nodeDescriptorList.add(node);
}
}

@ -0,0 +1,47 @@
/*
* Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved.
* 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
*
* @summary converted from VM Testbase metaspace/stressHierarchy/stressHierarchy001.
* VM Testbase keywords: [nonconcurrent, javac, no_cds]
*
* @library /vmTestbase /test/lib
* @run driver jdk.test.lib.FileInstaller . .
* @build sun.hotspot.WhiteBox
* @run driver ClassFileInstaller sun.hotspot.WhiteBox
* sun.hotspot.WhiteBox$WhiteBoxPermission
* @run main/othervm
* -Xss10m
* -Xbootclasspath/a:.
* -XX:+UnlockDiagnosticVMOptions
* -XX:+WhiteBoxAPI
* metaspace.stressHierarchy.common.StressHierarchy1
* -treeDepth 70
* -minLevelSize 10
* -maxLevelSize 100
* -hierarchyType CLASSES
*/

@ -0,0 +1,47 @@
/*
* Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved.
* 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
*
* @summary converted from VM Testbase metaspace/stressHierarchy/stressHierarchy002.
* VM Testbase keywords: [nonconcurrent, javac, no_cds]
*
* @library /vmTestbase /test/lib
* @run driver jdk.test.lib.FileInstaller . .
* @build sun.hotspot.WhiteBox
* @run driver ClassFileInstaller sun.hotspot.WhiteBox
* sun.hotspot.WhiteBox$WhiteBoxPermission
* @run main/othervm
* -Xss10m
* -Xbootclasspath/a:.
* -XX:+UnlockDiagnosticVMOptions
* -XX:+WhiteBoxAPI
* metaspace.stressHierarchy.common.StressHierarchy2
* -treeDepth 70
* -minLevelSize 10
* -maxLevelSize 100
* -hierarchyType CLASSES
*/

@ -0,0 +1,47 @@
/*
* Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved.
* 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
*
* @summary converted from VM Testbase metaspace/stressHierarchy/stressHierarchy003.
* VM Testbase keywords: [nonconcurrent, javac, no_cds]
*
* @library /vmTestbase /test/lib
* @run driver jdk.test.lib.FileInstaller . .
* @build sun.hotspot.WhiteBox
* @run driver ClassFileInstaller sun.hotspot.WhiteBox
* sun.hotspot.WhiteBox$WhiteBoxPermission
* @run main/othervm
* -Xss10m
* -Xbootclasspath/a:.
* -XX:+UnlockDiagnosticVMOptions
* -XX:+WhiteBoxAPI
* metaspace.stressHierarchy.common.StressHierarchy1
* -treeDepth 70
* -minLevelSize 10
* -maxLevelSize 100
* -hierarchyType INTERFACES
*/

@ -0,0 +1,47 @@
/*
* Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved.
* 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
*
* @summary converted from VM Testbase metaspace/stressHierarchy/stressHierarchy004.
* VM Testbase keywords: [nonconcurrent, javac, no_cds]
*
* @library /vmTestbase /test/lib
* @run driver jdk.test.lib.FileInstaller . .
* @build sun.hotspot.WhiteBox
* @run driver ClassFileInstaller sun.hotspot.WhiteBox
* sun.hotspot.WhiteBox$WhiteBoxPermission
* @run main/othervm
* -Xss10m
* -Xbootclasspath/a:.
* -XX:+UnlockDiagnosticVMOptions
* -XX:+WhiteBoxAPI
* metaspace.stressHierarchy.common.StressHierarchy2
* -treeDepth 70
* -minLevelSize 10
* -maxLevelSize 100
* -hierarchyType INTERFACES
*/

@ -0,0 +1,47 @@
/*
* Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved.
* 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
*
* @summary converted from VM Testbase metaspace/stressHierarchy/stressHierarchy005.
* VM Testbase keywords: [nonconcurrent, javac, no_cds]
*
* @library /vmTestbase /test/lib
* @run driver jdk.test.lib.FileInstaller . .
* @build sun.hotspot.WhiteBox
* @run driver ClassFileInstaller sun.hotspot.WhiteBox
* sun.hotspot.WhiteBox$WhiteBoxPermission
* @run main/othervm
* -Xss10m
* -Xbootclasspath/a:.
* -XX:+UnlockDiagnosticVMOptions
* -XX:+WhiteBoxAPI
* metaspace.stressHierarchy.common.StressHierarchy1
* -treeDepth 70
* -minLevelSize 10
* -maxLevelSize 100
* -hierarchyType MIXED
*/

@ -0,0 +1,47 @@
/*
* Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved.
* 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
*
* @summary converted from VM Testbase metaspace/stressHierarchy/stressHierarchy006.
* VM Testbase keywords: [nonconcurrent, javac, no_cds]
*
* @library /vmTestbase /test/lib
* @run driver jdk.test.lib.FileInstaller . .
* @build sun.hotspot.WhiteBox
* @run driver ClassFileInstaller sun.hotspot.WhiteBox
* sun.hotspot.WhiteBox$WhiteBoxPermission
* @run main/othervm
* -Xss10m
* -Xbootclasspath/a:.
* -XX:+UnlockDiagnosticVMOptions
* -XX:+WhiteBoxAPI
* metaspace.stressHierarchy.common.StressHierarchy2
* -treeDepth 70
* -minLevelSize 10
* -maxLevelSize 100
* -hierarchyType MIXED
*/

@ -0,0 +1,51 @@
/*
* Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved.
* 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
*
* @summary converted from VM Testbase metaspace/stressHierarchy/stressHierarchy007.
* VM Testbase keywords: [nonconcurrent, javac, no_cds]
*
* @library /vmTestbase /test/lib
* @run driver jdk.test.lib.FileInstaller . .
* @build sun.hotspot.WhiteBox
* @run driver ClassFileInstaller sun.hotspot.WhiteBox
* sun.hotspot.WhiteBox$WhiteBoxPermission
* @comment generate and compile metaspace.stressHierarchy.common.HumongousClass
* @run driver metaspace.stressHierarchy.common.GenClassesBuilder
* @run main/othervm
* -XX:MaxMetaspaceSize=450m
* -Xss10m
* -Xbootclasspath/a:.
* -XX:+UnlockDiagnosticVMOptions
* -XX:+WhiteBoxAPI
* metaspace.stressHierarchy.common.StressHierarchy3
* -treeDepth 70
* -minLevelSize 10
* -maxLevelSize 100
* -hierarchyType CLASSES
* -triggerUnloadingByFillingMetaspace
*/

@ -0,0 +1,51 @@
/*
* Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved.
* 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
*
* @summary converted from VM Testbase metaspace/stressHierarchy/stressHierarchy008.
* VM Testbase keywords: [nonconcurrent, javac, no_cds]
*
* @library /vmTestbase /test/lib
* @run driver jdk.test.lib.FileInstaller . .
* @build sun.hotspot.WhiteBox
* @run driver ClassFileInstaller sun.hotspot.WhiteBox
* sun.hotspot.WhiteBox$WhiteBoxPermission
* @comment generate and compile metaspace.stressHierarchy.common.HumongousClass
* @run driver metaspace.stressHierarchy.common.GenClassesBuilder
* @run main/othervm
* -XX:MaxMetaspaceSize=450m
* -Xss10m
* -Xbootclasspath/a:.
* -XX:+UnlockDiagnosticVMOptions
* -XX:+WhiteBoxAPI
* metaspace.stressHierarchy.common.StressHierarchy2
* -treeDepth 70
* -minLevelSize 10
* -maxLevelSize 100
* -hierarchyType CLASSES
* -triggerUnloadingByFillingMetaspace
*/

@ -0,0 +1,51 @@
/*
* Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved.
* 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
*
* @summary converted from VM Testbase metaspace/stressHierarchy/stressHierarchy009.
* VM Testbase keywords: [nonconcurrent, javac, no_cds]
*
* @library /vmTestbase /test/lib
* @run driver jdk.test.lib.FileInstaller . .
* @build sun.hotspot.WhiteBox
* @run driver ClassFileInstaller sun.hotspot.WhiteBox
* sun.hotspot.WhiteBox$WhiteBoxPermission
* @comment generate and compile metaspace.stressHierarchy.common.HumongousClass
* @run driver metaspace.stressHierarchy.common.GenClassesBuilder
* @run main/othervm
* -XX:MaxMetaspaceSize=450m
* -Xss10m
* -Xbootclasspath/a:.
* -XX:+UnlockDiagnosticVMOptions
* -XX:+WhiteBoxAPI
* metaspace.stressHierarchy.common.StressHierarchy3
* -treeDepth 70
* -minLevelSize 10
* -maxLevelSize 100
* -hierarchyType INTERFACES
* -triggerUnloadingByFillingMetaspace
*/

@ -0,0 +1,51 @@
/*
* Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved.
* 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
*
* @summary converted from VM Testbase metaspace/stressHierarchy/stressHierarchy010.
* VM Testbase keywords: [nonconcurrent, javac, no_cds]
*
* @library /vmTestbase /test/lib
* @run driver jdk.test.lib.FileInstaller . .
* @build sun.hotspot.WhiteBox
* @run driver ClassFileInstaller sun.hotspot.WhiteBox
* sun.hotspot.WhiteBox$WhiteBoxPermission
* @comment generate and compile metaspace.stressHierarchy.common.HumongousClass
* @run driver metaspace.stressHierarchy.common.GenClassesBuilder
* @run main/othervm
* -XX:MaxMetaspaceSize=450m
* -Xss10m
* -Xbootclasspath/a:.
* -XX:+UnlockDiagnosticVMOptions
* -XX:+WhiteBoxAPI
* metaspace.stressHierarchy.common.StressHierarchy2
* -treeDepth 70
* -minLevelSize 10
* -maxLevelSize 100
* -hierarchyType INTERFACES
* -triggerUnloadingByFillingMetaspace
*/

@ -0,0 +1,51 @@
/*
* Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved.
* 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
*
* @summary converted from VM Testbase metaspace/stressHierarchy/stressHierarchy011.
* VM Testbase keywords: [nonconcurrent, javac, no_cds]
*
* @library /vmTestbase /test/lib
* @run driver jdk.test.lib.FileInstaller . .
* @build sun.hotspot.WhiteBox
* @run driver ClassFileInstaller sun.hotspot.WhiteBox
* sun.hotspot.WhiteBox$WhiteBoxPermission
* @comment generate and compile metaspace.stressHierarchy.common.HumongousClass
* @run driver metaspace.stressHierarchy.common.GenClassesBuilder
* @run main/othervm
* -XX:MaxMetaspaceSize=450m
* -Xss10m
* -Xbootclasspath/a:.
* -XX:+UnlockDiagnosticVMOptions
* -XX:+WhiteBoxAPI
* metaspace.stressHierarchy.common.StressHierarchy3
* -treeDepth 70
* -minLevelSize 10
* -maxLevelSize 100
* -hierarchyType MIXED
* -triggerUnloadingByFillingMetaspace
*/

@ -0,0 +1,51 @@
/*
* Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved.
* 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
*
* @summary converted from VM Testbase metaspace/stressHierarchy/stressHierarchy012.
* VM Testbase keywords: [nonconcurrent, javac, no_cds]
*
* @library /vmTestbase /test/lib
* @run driver jdk.test.lib.FileInstaller . .
* @build sun.hotspot.WhiteBox
* @run driver ClassFileInstaller sun.hotspot.WhiteBox
* sun.hotspot.WhiteBox$WhiteBoxPermission
* @comment generate and compile metaspace.stressHierarchy.common.HumongousClass
* @run driver metaspace.stressHierarchy.common.GenClassesBuilder
* @run main/othervm
* -XX:MaxMetaspaceSize=450m
* -Xss10m
* -Xbootclasspath/a:.
* -XX:+UnlockDiagnosticVMOptions
* -XX:+WhiteBoxAPI
* metaspace.stressHierarchy.common.StressHierarchy2
* -treeDepth 70
* -minLevelSize 10
* -maxLevelSize 100
* -hierarchyType MIXED
* -triggerUnloadingByFillingMetaspace
*/

@ -0,0 +1,47 @@
/*
* Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved.
* 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
*
* @summary converted from VM Testbase metaspace/stressHierarchy/stressHierarchy013.
* VM Testbase keywords: [nonconcurrent, javac, no_cds]
*
* @library /vmTestbase /test/lib
* @run driver jdk.test.lib.FileInstaller . .
* @build sun.hotspot.WhiteBox
* @run driver ClassFileInstaller sun.hotspot.WhiteBox
* sun.hotspot.WhiteBox$WhiteBoxPermission
* @run main/othervm
* -Xss10m
* -Xbootclasspath/a:.
* -XX:+UnlockDiagnosticVMOptions
* -XX:+WhiteBoxAPI
* metaspace.stressHierarchy.common.StressHierarchy3
* -treeDepth 70
* -minLevelSize 10
* -maxLevelSize 100
* -hierarchyType CLASSES
*/

@ -0,0 +1,47 @@
/*
* Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved.
* 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
*
* @summary converted from VM Testbase metaspace/stressHierarchy/stressHierarchy014.
* VM Testbase keywords: [nonconcurrent, javac, no_cds]
*
* @library /vmTestbase /test/lib
* @run driver jdk.test.lib.FileInstaller . .
* @build sun.hotspot.WhiteBox
* @run driver ClassFileInstaller sun.hotspot.WhiteBox
* sun.hotspot.WhiteBox$WhiteBoxPermission
* @run main/othervm
* -Xss10m
* -Xbootclasspath/a:.
* -XX:+UnlockDiagnosticVMOptions
* -XX:+WhiteBoxAPI
* metaspace.stressHierarchy.common.StressHierarchy3
* -treeDepth 70
* -minLevelSize 10
* -maxLevelSize 100
* -hierarchyType INTERFACES
*/

@ -0,0 +1,47 @@
/*
* Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved.
* 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
*
* @summary converted from VM Testbase metaspace/stressHierarchy/stressHierarchy015.
* VM Testbase keywords: [nonconcurrent, javac, no_cds]
*
* @library /vmTestbase /test/lib
* @run driver jdk.test.lib.FileInstaller . .
* @build sun.hotspot.WhiteBox
* @run driver ClassFileInstaller sun.hotspot.WhiteBox
* sun.hotspot.WhiteBox$WhiteBoxPermission
* @run main/othervm
* -Xss10m
* -Xbootclasspath/a:.
* -XX:+UnlockDiagnosticVMOptions
* -XX:+WhiteBoxAPI
* metaspace.stressHierarchy.common.StressHierarchy3
* -treeDepth 70
* -minLevelSize 10
* -maxLevelSize 100
* -hierarchyType MIXED
*/