Merge
This commit is contained in:
commit
e747db29cd
@ -30,11 +30,9 @@
|
|||||||
*
|
*
|
||||||
* @author Mandy Chung
|
* @author Mandy Chung
|
||||||
*
|
*
|
||||||
* @build CollectionUsageThreshold MemoryUtil
|
* @library /lib/testlibrary/
|
||||||
* @run main/othervm/timeout=300 -XX:+PrintGCDetails -XX:+UseSerialGC CollectionUsageThreshold
|
* @build CollectionUsageThreshold MemoryUtil RunUtil
|
||||||
* @run main/othervm/timeout=300 -XX:+PrintGCDetails -XX:+UseParallelGC CollectionUsageThreshold
|
* @run main/timeout=300 CollectionUsageThreshold
|
||||||
* @run main/othervm/timeout=300 -XX:+PrintGCDetails -XX:+UseG1GC CollectionUsageThreshold
|
|
||||||
* @run main/othervm/timeout=300 -XX:+PrintGCDetails -XX:+UseConcMarkSweepGC CollectionUsageThreshold
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
@ -61,6 +59,20 @@ public class CollectionUsageThreshold {
|
|||||||
// finishes checking the low memory notification result
|
// finishes checking the low memory notification result
|
||||||
private static final CyclicBarrier barrier = new CyclicBarrier(2);
|
private static final CyclicBarrier barrier = new CyclicBarrier(2);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Run the test multiple times with different GC versions.
|
||||||
|
* First with default command line specified by the framework.
|
||||||
|
* Then with GC versions specified by the test.
|
||||||
|
*/
|
||||||
|
public static void main(String a[]) throws Throwable {
|
||||||
|
final String main = "CollectionUsageThreshold$TestMain";
|
||||||
|
RunUtil.runTestKeepGcOpts(main);
|
||||||
|
RunUtil.runTestClearGcOpts(main, "-XX:+UseSerialGC");
|
||||||
|
RunUtil.runTestClearGcOpts(main, "-XX:+UseParallelGC");
|
||||||
|
RunUtil.runTestClearGcOpts(main, "-XX:+UseG1GC");
|
||||||
|
RunUtil.runTestClearGcOpts(main, "-XX:+UseConcMarkSweepGC");
|
||||||
|
}
|
||||||
|
|
||||||
static class PoolRecord {
|
static class PoolRecord {
|
||||||
private final MemoryPoolMXBean pool;
|
private final MemoryPoolMXBean pool;
|
||||||
private final AtomicInteger listenerInvoked = new AtomicInteger(0);
|
private final AtomicInteger listenerInvoked = new AtomicInteger(0);
|
||||||
@ -110,88 +122,90 @@ public class CollectionUsageThreshold {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void main(String args[]) throws Exception {
|
private static class TestMain {
|
||||||
if (args.length > 0 && args[0].equals("trace")) {
|
public static void main(String args[]) throws Exception {
|
||||||
trace = true;
|
if (args.length > 0 && args[0].equals("trace")) {
|
||||||
}
|
trace = true;
|
||||||
|
}
|
||||||
|
|
||||||
List<MemoryPoolMXBean> pools = getMemoryPoolMXBeans();
|
List<MemoryPoolMXBean> pools = getMemoryPoolMXBeans();
|
||||||
List<MemoryManagerMXBean> managers = getMemoryManagerMXBeans();
|
List<MemoryManagerMXBean> managers = getMemoryManagerMXBeans();
|
||||||
|
|
||||||
if (trace) {
|
if (trace) {
|
||||||
MemoryUtil.printMemoryPools(pools);
|
MemoryUtil.printMemoryPools(pools);
|
||||||
MemoryUtil.printMemoryManagers(managers);
|
MemoryUtil.printMemoryManagers(managers);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Find the Old generation which supports low memory detection
|
// Find the Old generation which supports low memory detection
|
||||||
for (MemoryPoolMXBean p : pools) {
|
for (MemoryPoolMXBean p : pools) {
|
||||||
if (p.isUsageThresholdSupported() && p.isCollectionUsageThresholdSupported()) {
|
if (p.isUsageThresholdSupported() && p.isCollectionUsageThresholdSupported()) {
|
||||||
if (p.getName().toLowerCase().contains("perm")) {
|
if (p.getName().toLowerCase().contains("perm")) {
|
||||||
// if we have a "perm gen" pool increase the number of expected
|
// if we have a "perm gen" pool increase the number of expected
|
||||||
// memory pools by one.
|
// memory pools by one.
|
||||||
numMemoryPools++;
|
numMemoryPools++;
|
||||||
}
|
}
|
||||||
PoolRecord pr = new PoolRecord(p);
|
PoolRecord pr = new PoolRecord(p);
|
||||||
result.put(p.getName(), pr);
|
result.put(p.getName(), pr);
|
||||||
if (result.size() == numMemoryPools) {
|
if (result.size() == numMemoryPools) {
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
if (result.size() != numMemoryPools) {
|
||||||
if (result.size() != numMemoryPools) {
|
throw new RuntimeException("Unexpected number of selected pools");
|
||||||
throw new RuntimeException("Unexpected number of selected pools");
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
// This test creates a checker thread responsible for checking
|
|
||||||
// the low memory notifications. It blocks until a permit
|
|
||||||
// from the signals semaphore is available.
|
|
||||||
Checker checker = new Checker("Checker thread");
|
|
||||||
checker.setDaemon(true);
|
|
||||||
checker.start();
|
|
||||||
|
|
||||||
for (PoolRecord pr : result.values()) {
|
|
||||||
pr.getPool().setCollectionUsageThreshold(THRESHOLD);
|
|
||||||
System.out.println("Collection usage threshold of " +
|
|
||||||
pr.getPool().getName() + " set to " + THRESHOLD);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SensorListener listener = new SensorListener();
|
try {
|
||||||
NotificationEmitter emitter = (NotificationEmitter) mm;
|
// This test creates a checker thread responsible for checking
|
||||||
emitter.addNotificationListener(listener, null, null);
|
// the low memory notifications. It blocks until a permit
|
||||||
|
// from the signals semaphore is available.
|
||||||
|
Checker checker = new Checker("Checker thread");
|
||||||
|
checker.setDaemon(true);
|
||||||
|
checker.start();
|
||||||
|
|
||||||
// The main thread invokes GC to trigger the VM to perform
|
for (PoolRecord pr : result.values()) {
|
||||||
// low memory detection and then waits until the checker thread
|
pr.getPool().setCollectionUsageThreshold(THRESHOLD);
|
||||||
// finishes its work to check for a low-memory notification.
|
System.out.println("Collection usage threshold of " +
|
||||||
//
|
pr.getPool().getName() + " set to " + THRESHOLD);
|
||||||
// At GC time, VM will issue low-memory notification and invoke
|
}
|
||||||
// the listener which will release a permit to the signals semaphore.
|
|
||||||
// When the checker thread acquires the permit and finishes
|
SensorListener listener = new SensorListener();
|
||||||
// checking the low-memory notification, it will also call
|
NotificationEmitter emitter = (NotificationEmitter) mm;
|
||||||
// barrier.await() to signal the main thread to resume its work.
|
emitter.addNotificationListener(listener, null, null);
|
||||||
for (int i = 0; i < NUM_GCS; i++) {
|
|
||||||
invokeGC();
|
// The main thread invokes GC to trigger the VM to perform
|
||||||
barrier.await();
|
// low memory detection and then waits until the checker thread
|
||||||
}
|
// finishes its work to check for a low-memory notification.
|
||||||
} finally {
|
//
|
||||||
// restore the default
|
// At GC time, VM will issue low-memory notification and invoke
|
||||||
for (PoolRecord pr : result.values()) {
|
// the listener which will release a permit to the signals semaphore.
|
||||||
pr.getPool().setCollectionUsageThreshold(0);
|
// When the checker thread acquires the permit and finishes
|
||||||
|
// checking the low-memory notification, it will also call
|
||||||
|
// barrier.await() to signal the main thread to resume its work.
|
||||||
|
for (int i = 0; i < NUM_GCS; i++) {
|
||||||
|
invokeGC();
|
||||||
|
barrier.await();
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
// restore the default
|
||||||
|
for (PoolRecord pr : result.values()) {
|
||||||
|
pr.getPool().setCollectionUsageThreshold(0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
System.out.println(RunUtil.successMessage);
|
||||||
}
|
}
|
||||||
System.out.println("Test passed.");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private static void invokeGC() {
|
private static void invokeGC() {
|
||||||
System.out.println("Calling System.gc()");
|
System.out.println("Calling System.gc()");
|
||||||
numGCs++;
|
numGCs++;
|
||||||
mm.gc();
|
mm.gc();
|
||||||
|
|
||||||
if (trace) {
|
if (trace) {
|
||||||
for (PoolRecord pr : result.values()) {
|
for (PoolRecord pr : result.values()) {
|
||||||
System.out.println("Usage after GC for: " + pr.getPool().getName());
|
System.out.println("Usage after GC for: " + pr.getPool().getName());
|
||||||
MemoryUtil.printMemoryUsage(pr.getPool().getUsage());
|
MemoryUtil.printMemoryUsage(pr.getPool().getUsage());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -30,11 +30,9 @@
|
|||||||
*
|
*
|
||||||
* @author Mandy Chung
|
* @author Mandy Chung
|
||||||
*
|
*
|
||||||
* @build LowMemoryTest MemoryUtil
|
* @library /lib/testlibrary/
|
||||||
* @run main/othervm/timeout=600 LowMemoryTest
|
* @build LowMemoryTest MemoryUtil RunUtil
|
||||||
* @run main/othervm/timeout=600 -XX:+UseConcMarkSweepGC LowMemoryTest
|
* @run main/timeout=600 LowMemoryTest
|
||||||
* @run main/othervm/timeout=600 -XX:+UseParallelGC LowMemoryTest
|
|
||||||
* @run main/othervm/timeout=600 -XX:+UseSerialGC LowMemoryTest
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import java.lang.management.*;
|
import java.lang.management.*;
|
||||||
@ -54,6 +52,20 @@ public class LowMemoryTest {
|
|||||||
private static final int NUM_CHUNKS = 2;
|
private static final int NUM_CHUNKS = 2;
|
||||||
private static long chunkSize;
|
private static long chunkSize;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Run the test multiple times with different GC versions.
|
||||||
|
* First with default command line specified by the framework.
|
||||||
|
* Then with GC versions specified by the test.
|
||||||
|
*/
|
||||||
|
public static void main(String a[]) throws Throwable {
|
||||||
|
final String main = "LowMemoryTest$TestMain";
|
||||||
|
RunUtil.runTestKeepGcOpts(main);
|
||||||
|
RunUtil.runTestClearGcOpts(main, "-XX:+UseSerialGC");
|
||||||
|
RunUtil.runTestClearGcOpts(main, "-XX:+UseParallelGC");
|
||||||
|
RunUtil.runTestClearGcOpts(main, "-XX:+UseG1GC");
|
||||||
|
RunUtil.runTestClearGcOpts(main, "-XX:+UseConcMarkSweepGC");
|
||||||
|
}
|
||||||
|
|
||||||
private static volatile boolean listenerInvoked = false;
|
private static volatile boolean listenerInvoked = false;
|
||||||
static class SensorListener implements NotificationListener {
|
static class SensorListener implements NotificationListener {
|
||||||
@Override
|
@Override
|
||||||
@ -107,77 +119,80 @@ public class LowMemoryTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static long newThreshold;
|
private static long newThreshold;
|
||||||
public static void main(String args[]) throws Exception {
|
|
||||||
if (args.length > 0 && args[0].equals("trace")) {
|
|
||||||
trace = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Find the Old generation which supports low memory detection
|
private static class TestMain {
|
||||||
ListIterator iter = pools.listIterator();
|
public static void main(String args[]) throws Exception {
|
||||||
while (iter.hasNext()) {
|
if (args.length > 0 && args[0].equals("trace")) {
|
||||||
MemoryPoolMXBean p = (MemoryPoolMXBean) iter.next();
|
trace = true;
|
||||||
if (p.getType() == MemoryType.HEAP &&
|
|
||||||
p.isUsageThresholdSupported()) {
|
|
||||||
mpool = p;
|
|
||||||
if (trace) {
|
|
||||||
System.out.println("Selected memory pool for low memory " +
|
|
||||||
"detection.");
|
|
||||||
MemoryUtil.printMemoryPool(mpool);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
TestListener listener = new TestListener();
|
// Find the Old generation which supports low memory detection
|
||||||
SensorListener l2 = new SensorListener();
|
ListIterator iter = pools.listIterator();
|
||||||
NotificationEmitter emitter = (NotificationEmitter) mm;
|
while (iter.hasNext()) {
|
||||||
emitter.addNotificationListener(listener, null, null);
|
MemoryPoolMXBean p = (MemoryPoolMXBean) iter.next();
|
||||||
emitter.addNotificationListener(l2, null, null);
|
if (p.getType() == MemoryType.HEAP &&
|
||||||
|
p.isUsageThresholdSupported()) {
|
||||||
|
mpool = p;
|
||||||
|
if (trace) {
|
||||||
|
System.out.println("Selected memory pool for low memory " +
|
||||||
|
"detection.");
|
||||||
|
MemoryUtil.printMemoryPool(mpool);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Thread allocator = new AllocatorThread();
|
TestListener listener = new TestListener();
|
||||||
Thread sweeper = new SweeperThread();
|
SensorListener l2 = new SensorListener();
|
||||||
|
NotificationEmitter emitter = (NotificationEmitter) mm;
|
||||||
|
emitter.addNotificationListener(listener, null, null);
|
||||||
|
emitter.addNotificationListener(l2, null, null);
|
||||||
|
|
||||||
// Now set threshold
|
Thread allocator = new AllocatorThread();
|
||||||
MemoryUsage mu = mpool.getUsage();
|
Thread sweeper = new SweeperThread();
|
||||||
chunkSize = (mu.getMax() - mu.getUsed()) / 20;
|
|
||||||
newThreshold = mu.getUsed() + (chunkSize * NUM_CHUNKS);
|
|
||||||
|
|
||||||
System.out.println("Setting threshold for " + mpool.getName() +
|
// Now set threshold
|
||||||
" from " + mpool.getUsageThreshold() + " to " + newThreshold +
|
MemoryUsage mu = mpool.getUsage();
|
||||||
". Current used = " + mu.getUsed());
|
chunkSize = (mu.getMax() - mu.getUsed()) / 20;
|
||||||
mpool.setUsageThreshold(newThreshold);
|
newThreshold = mu.getUsed() + (chunkSize * NUM_CHUNKS);
|
||||||
|
|
||||||
if (mpool.getUsageThreshold() != newThreshold) {
|
System.out.println("Setting threshold for " + mpool.getName() +
|
||||||
throw new RuntimeException("TEST FAILED: " +
|
" from " + mpool.getUsageThreshold() + " to " + newThreshold +
|
||||||
|
". Current used = " + mu.getUsed());
|
||||||
|
mpool.setUsageThreshold(newThreshold);
|
||||||
|
|
||||||
|
if (mpool.getUsageThreshold() != newThreshold) {
|
||||||
|
throw new RuntimeException("TEST FAILED: " +
|
||||||
"Threshold for Memory pool " + mpool.getName() +
|
"Threshold for Memory pool " + mpool.getName() +
|
||||||
"is " + mpool.getUsageThreshold() + " but expected to be" +
|
"is " + mpool.getUsageThreshold() + " but expected to be" +
|
||||||
newThreshold);
|
newThreshold);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
allocator.start();
|
allocator.start();
|
||||||
// Force Allocator start first
|
// Force Allocator start first
|
||||||
phaser.arriveAndAwaitAdvance();
|
|
||||||
sweeper.start();
|
|
||||||
|
|
||||||
|
|
||||||
try {
|
|
||||||
allocator.join();
|
|
||||||
// Wait until AllocatorThread's done
|
|
||||||
phaser.arriveAndAwaitAdvance();
|
phaser.arriveAndAwaitAdvance();
|
||||||
sweeper.join();
|
sweeper.start();
|
||||||
} catch (InterruptedException e) {
|
|
||||||
System.out.println("Unexpected exception:" + e);
|
|
||||||
testFailed = true;
|
try {
|
||||||
|
allocator.join();
|
||||||
|
// Wait until AllocatorThread's done
|
||||||
|
phaser.arriveAndAwaitAdvance();
|
||||||
|
sweeper.join();
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
System.out.println("Unexpected exception:" + e);
|
||||||
|
testFailed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
listener.checkResult();
|
||||||
|
|
||||||
|
if (testFailed)
|
||||||
|
throw new RuntimeException("TEST FAILED.");
|
||||||
|
|
||||||
|
System.out.println(RunUtil.successMessage);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
listener.checkResult();
|
|
||||||
|
|
||||||
if (testFailed)
|
|
||||||
throw new RuntimeException("TEST FAILED.");
|
|
||||||
|
|
||||||
System.out.println("Test passed.");
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void goSleep(long ms) {
|
private static void goSleep(long ms) {
|
||||||
|
@ -32,11 +32,9 @@
|
|||||||
* @summary Basic Test for MemoryPool.resetPeakUsage()
|
* @summary Basic Test for MemoryPool.resetPeakUsage()
|
||||||
* @author Mandy Chung
|
* @author Mandy Chung
|
||||||
*
|
*
|
||||||
* @build ResetPeakMemoryUsage MemoryUtil
|
* @library /lib/testlibrary/
|
||||||
* @run main/othervm -XX:+PrintGCDetails -XX:+UseSerialGC -Xms256m -XX:MarkSweepAlwaysCompactCount=1 -Xmn8m ResetPeakMemoryUsage
|
* @build ResetPeakMemoryUsage MemoryUtil RunUtil
|
||||||
* @run main/othervm -XX:+PrintGCDetails -XX:+UseConcMarkSweepGC -Xms256m -Xmn8m ResetPeakMemoryUsage
|
* @run main ResetPeakMemoryUsage
|
||||||
* @run main/othervm -XX:+PrintGCDetails -XX:+UseParallelGC -Xms256m -Xmn8m ResetPeakMemoryUsage
|
|
||||||
* @run main/othervm -XX:+PrintGCDetails -XX:+UseG1GC -Xms256m -Xmn8m -XX:G1HeapRegionSize=1m ResetPeakMemoryUsage
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import java.lang.management.*;
|
import java.lang.management.*;
|
||||||
@ -47,24 +45,42 @@ public class ResetPeakMemoryUsage {
|
|||||||
// make public so that it can't be optimized away easily
|
// make public so that it can't be optimized away easily
|
||||||
public static Object[] obj;
|
public static Object[] obj;
|
||||||
|
|
||||||
public static void main(String[] argv) {
|
/**
|
||||||
List pools = ManagementFactory.getMemoryPoolMXBeans();
|
* Run the test multiple times with different GC versions.
|
||||||
ListIterator iter = pools.listIterator();
|
* First with default command line specified by the framework.
|
||||||
boolean found = false;
|
* Then with all GC versions specified by the test.
|
||||||
while (iter.hasNext()) {
|
*/
|
||||||
MemoryPoolMXBean p = (MemoryPoolMXBean) iter.next();
|
public static void main(String a[]) throws Throwable {
|
||||||
// only check heap pools that support usage threshold
|
final String main = "ResetPeakMemoryUsage$TestMain";
|
||||||
// this is typically only the old generation space
|
final String ms = "-Xms256m";
|
||||||
// since the other spaces are expected to get filled up
|
final String mn = "-Xmn8m";
|
||||||
if (p.getType() == MemoryType.HEAP &&
|
RunUtil.runTestClearGcOpts(main, ms, mn, "-XX:+UseConcMarkSweepGC");
|
||||||
p.isUsageThresholdSupported())
|
RunUtil.runTestClearGcOpts(main, ms, mn, "-XX:+UseParallelGC");
|
||||||
{
|
RunUtil.runTestClearGcOpts(main, ms, mn, "-XX:+UseG1GC", "-XX:G1HeapRegionSize=1m");
|
||||||
found = true;
|
RunUtil.runTestClearGcOpts(main, ms, mn, "-XX:+UseSerialGC",
|
||||||
testPool(p);
|
"-XX:MarkSweepAlwaysCompactCount=1");
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class TestMain {
|
||||||
|
public static void main(String[] argv) {
|
||||||
|
List pools = ManagementFactory.getMemoryPoolMXBeans();
|
||||||
|
ListIterator iter = pools.listIterator();
|
||||||
|
boolean found = false;
|
||||||
|
while (iter.hasNext()) {
|
||||||
|
MemoryPoolMXBean p = (MemoryPoolMXBean) iter.next();
|
||||||
|
// only check heap pools that support usage threshold
|
||||||
|
// this is typically only the old generation space
|
||||||
|
// since the other spaces are expected to get filled up
|
||||||
|
if (p.getType() == MemoryType.HEAP &&
|
||||||
|
p.isUsageThresholdSupported())
|
||||||
|
{
|
||||||
|
found = true;
|
||||||
|
testPool(p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!found) {
|
||||||
|
throw new RuntimeException("No heap pool found");
|
||||||
}
|
}
|
||||||
}
|
|
||||||
if (!found) {
|
|
||||||
throw new RuntimeException("No heap pool found");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -142,7 +158,7 @@ public class ResetPeakMemoryUsage {
|
|||||||
formatSize("previous peak", peak2.getUsed()));
|
formatSize("previous peak", peak2.getUsed()));
|
||||||
}
|
}
|
||||||
|
|
||||||
System.out.println("Test passed.");
|
System.out.println(RunUtil.successMessage);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String INDENT = " ";
|
private static String INDENT = " ";
|
||||||
|
84
jdk/test/java/lang/management/MemoryMXBean/RunUtil.java
Normal file
84
jdk/test/java/lang/management/MemoryMXBean/RunUtil.java
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2014, 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Utility class for launching a test in a separate JVM.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import jdk.testlibrary.OutputAnalyzer;
|
||||||
|
import jdk.testlibrary.Utils;
|
||||||
|
import jdk.testlibrary.ProcessTools;
|
||||||
|
import jdk.testlibrary.JDKToolFinder;
|
||||||
|
|
||||||
|
public class RunUtil {
|
||||||
|
|
||||||
|
// Used to mark that the test has passed successfully.
|
||||||
|
public static final String successMessage = "Test passed.";
|
||||||
|
|
||||||
|
public static void runTestClearGcOpts(String main, String... testOpts) throws Throwable {
|
||||||
|
runTest(main, true, testOpts);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void runTestKeepGcOpts(String main, String... testOpts) throws Throwable {
|
||||||
|
runTest(main, false, testOpts);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Runs a test in a separate JVM.
|
||||||
|
* command line like:
|
||||||
|
* {test_jdk}/bin/java {defaultopts} -cp {test.class.path} {testopts} main
|
||||||
|
*
|
||||||
|
* {defaultopts} are the default java options set by the framework.
|
||||||
|
* Default GC options in {defaultopts} may be removed.
|
||||||
|
* This is used when the test specifies its own GC options.
|
||||||
|
*
|
||||||
|
* @param main Name of the main class.
|
||||||
|
* @param clearGcOpts true if the default GC options should be removed.
|
||||||
|
* @param testOpts java options specified by the test.
|
||||||
|
*/
|
||||||
|
private static void runTest(String main, boolean clearGcOpts, String... testOpts)
|
||||||
|
throws Throwable {
|
||||||
|
List<String> opts = new ArrayList<>();
|
||||||
|
opts.add(JDKToolFinder.getJDKTool("java"));
|
||||||
|
opts.addAll(Arrays.asList(Utils.getTestJavaOpts()));
|
||||||
|
opts.add("-cp");
|
||||||
|
opts.add(System.getProperty("test.class.path", "test.class.path"));
|
||||||
|
opts.add("-XX:+PrintGCDetails");
|
||||||
|
|
||||||
|
if (clearGcOpts) {
|
||||||
|
opts = Utils.removeGcOpts(opts);
|
||||||
|
}
|
||||||
|
opts.addAll(Arrays.asList(testOpts));
|
||||||
|
opts.add(main);
|
||||||
|
|
||||||
|
OutputAnalyzer output = ProcessTools.executeProcess(opts.toArray(new String[0]));
|
||||||
|
output.shouldHaveExitValue(0);
|
||||||
|
if (output.getStdout().indexOf(successMessage) < 0) {
|
||||||
|
throw new Exception("output missing '" + successMessage + "'");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -119,6 +119,26 @@ public final class Utils {
|
|||||||
return opts.toArray(new String[0]);
|
return opts.toArray(new String[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes any options specifying which GC to use, for example "-XX:+UseG1GC".
|
||||||
|
* Removes any options matching: -XX:(+/-)Use*GC
|
||||||
|
* Used when a test need to set its own GC version. Then any
|
||||||
|
* GC specified by the framework must first be removed.
|
||||||
|
* @return A copy of given opts with all GC options removed.
|
||||||
|
*/
|
||||||
|
private static final Pattern useGcPattern = Pattern.compile("\\-XX\\:[\\+\\-]Use.+GC");
|
||||||
|
public static List<String> removeGcOpts(List<String> opts) {
|
||||||
|
List<String> optsWithoutGC = new ArrayList<String>();
|
||||||
|
for (String opt : opts) {
|
||||||
|
if (useGcPattern.matcher(opt).matches()) {
|
||||||
|
System.out.println("removeGcOpts: removed " + opt);
|
||||||
|
} else {
|
||||||
|
optsWithoutGC.add(opt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return optsWithoutGC;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Splits a string by white space.
|
* Splits a string by white space.
|
||||||
* Works like String.split(), but returns an empty array
|
* Works like String.split(), but returns an empty array
|
||||||
|
Loading…
Reference in New Issue
Block a user