Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/test/java/lang/management/MemoryMXBean/CollectionUsageThreshold.java
38821 views
/*1* Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*/2223/*24* @test25* @bug 4959889 699296826* @summary Basic unit test of memory management testing:27* 1) setCollectionUsageThreshold() and getCollectionUsageThreshold()28* 2) test notification emitted for two different memory pools.29*30* @author Mandy Chung31*32* @library /lib/testlibrary/33* @build CollectionUsageThreshold MemoryUtil RunUtil34* @run main/timeout=300 CollectionUsageThreshold35*/3637import java.util.*;38import java.util.concurrent.*;39import java.util.concurrent.atomic.AtomicInteger;40import javax.management.*;41import javax.management.openmbean.CompositeData;42import java.lang.management.*;43import static java.lang.management.MemoryNotificationInfo.*;;44import static java.lang.management.ManagementFactory.*;4546public class CollectionUsageThreshold {47private static final MemoryMXBean mm = getMemoryMXBean();48private static final Map<String, PoolRecord> result = new HashMap<>();49private static boolean trace = false;50private static volatile int numMemoryPools = 1;51private static final int NUM_GCS = 3;52private static final int THRESHOLD = 10;53private static volatile int numGCs = 0;5455// semaphore to signal the arrival of a low memory notification56private static final Semaphore signals = new Semaphore(0);57// barrier for the main thread to wait until the checker thread58// finishes checking the low memory notification result59private static final CyclicBarrier barrier = new CyclicBarrier(2);6061/**62* Run the test multiple times with different GC versions.63* First with default command line specified by the framework.64* Then with GC versions specified by the test.65*/66public static void main(String a[]) throws Throwable {67final String main = "CollectionUsageThreshold$TestMain";68RunUtil.runTestKeepGcOpts(main);69RunUtil.runTestClearGcOpts(main, "-XX:+UseSerialGC");70RunUtil.runTestClearGcOpts(main, "-XX:+UseParallelGC");71RunUtil.runTestClearGcOpts(main, "-XX:+UseG1GC");72RunUtil.runTestClearGcOpts(main, "-XX:+UseConcMarkSweepGC");73}7475static class PoolRecord {76private final MemoryPoolMXBean pool;77private final AtomicInteger listenerInvoked = new AtomicInteger(0);78private volatile long notifCount = 0;79PoolRecord(MemoryPoolMXBean p) {80this.pool = p;81}82int getListenerInvokedCount() {83return listenerInvoked.get();84}85long getNotifCount() {86return notifCount;87}88MemoryPoolMXBean getPool() {89return pool;90}91void addNotification(MemoryNotificationInfo minfo) {92listenerInvoked.incrementAndGet();93notifCount = minfo.getCount();94}95}9697static class SensorListener implements NotificationListener {98@Override99public void handleNotification(Notification notif, Object handback) {100String type = notif.getType();101if (MEMORY_THRESHOLD_EXCEEDED.equals(type) ||102MEMORY_COLLECTION_THRESHOLD_EXCEEDED.equals(type)) {103MemoryNotificationInfo minfo = MemoryNotificationInfo.104from((CompositeData) notif.getUserData());105106MemoryUtil.printMemoryNotificationInfo(minfo, type);107PoolRecord pr = (PoolRecord) result.get(minfo.getPoolName());108if (pr == null) {109throw new RuntimeException("Pool " + minfo.getPoolName() +110" is not selected");111}112if (!MEMORY_COLLECTION_THRESHOLD_EXCEEDED.equals(type)) {113throw new RuntimeException("Pool " + minfo.getPoolName() +114" got unexpected notification type: " +115type);116}117pr.addNotification(minfo);118System.out.println("notifying the checker thread to check result");119signals.release();120}121}122}123124private static class TestMain {125public static void main(String args[]) throws Exception {126if (args.length > 0 && args[0].equals("trace")) {127trace = true;128}129130List<MemoryPoolMXBean> pools = getMemoryPoolMXBeans();131List<MemoryManagerMXBean> managers = getMemoryManagerMXBeans();132133if (trace) {134MemoryUtil.printMemoryPools(pools);135MemoryUtil.printMemoryManagers(managers);136}137138// Find the Old generation which supports low memory detection139for (MemoryPoolMXBean p : pools) {140if (p.isUsageThresholdSupported() && p.isCollectionUsageThresholdSupported()) {141if (p.getName().toLowerCase().contains("perm")) {142// if we have a "perm gen" pool increase the number of expected143// memory pools by one.144numMemoryPools++;145}146PoolRecord pr = new PoolRecord(p);147result.put(p.getName(), pr);148if (result.size() == numMemoryPools) {149break;150}151}152}153if (result.size() != numMemoryPools) {154throw new RuntimeException("Unexpected number of selected pools");155}156157try {158// This test creates a checker thread responsible for checking159// the low memory notifications. It blocks until a permit160// from the signals semaphore is available.161Checker checker = new Checker("Checker thread");162checker.setDaemon(true);163checker.start();164165for (PoolRecord pr : result.values()) {166pr.getPool().setCollectionUsageThreshold(THRESHOLD);167System.out.println("Collection usage threshold of " +168pr.getPool().getName() + " set to " + THRESHOLD);169}170171SensorListener listener = new SensorListener();172NotificationEmitter emitter = (NotificationEmitter) mm;173emitter.addNotificationListener(listener, null, null);174175// The main thread invokes GC to trigger the VM to perform176// low memory detection and then waits until the checker thread177// finishes its work to check for a low-memory notification.178//179// At GC time, VM will issue low-memory notification and invoke180// the listener which will release a permit to the signals semaphore.181// When the checker thread acquires the permit and finishes182// checking the low-memory notification, it will also call183// barrier.await() to signal the main thread to resume its work.184for (int i = 0; i < NUM_GCS; i++) {185invokeGC();186barrier.await();187}188} finally {189// restore the default190for (PoolRecord pr : result.values()) {191pr.getPool().setCollectionUsageThreshold(0);192}193}194System.out.println(RunUtil.successMessage);195}196197198private static void invokeGC() {199System.out.println("Calling System.gc()");200numGCs++;201mm.gc();202203if (trace) {204for (PoolRecord pr : result.values()) {205System.out.println("Usage after GC for: " + pr.getPool().getName());206MemoryUtil.printMemoryUsage(pr.getPool().getUsage());207}208}209}210}211212static class Checker extends Thread {213Checker(String name) {214super(name);215};216@Override217public void run() {218while (true) {219try {220signals.acquire(numMemoryPools);221checkResult();222} catch (InterruptedException | BrokenBarrierException e) {223throw new RuntimeException(e);224}225}226}227private void checkResult() throws InterruptedException, BrokenBarrierException {228for (PoolRecord pr : result.values()) {229if (pr.getListenerInvokedCount() != numGCs) {230fail("Listeners invoked count = " +231pr.getListenerInvokedCount() + " expected to be " +232numGCs);233}234if (pr.getNotifCount() != numGCs) {235fail("Notif Count = " +236pr.getNotifCount() + " expected to be " +237numGCs);238}239240long count = pr.getPool().getCollectionUsageThresholdCount();241if (count != numGCs) {242fail("CollectionUsageThresholdCount = " +243count + " expected to be " + numGCs);244}245if (!pr.getPool().isCollectionUsageThresholdExceeded()) {246fail("isCollectionUsageThresholdExceeded" +247" expected to be true");248}249}250// wait until the main thread is waiting for notification251barrier.await();252System.out.println("notifying main thread to continue - result checking finished");253}254255private void fail(String msg) {256// reset the barrier to cause BrokenBarrierException to avoid hanging257barrier.reset();258throw new RuntimeException(msg);259}260}261}262263264