4235N/A/*
4235N/A * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
4235N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4235N/A *
4235N/A * This code is free software; you can redistribute it and/or modify it
4235N/A * under the terms of the GNU General Public License version 2 only, as
4235N/A * published by the Free Software Foundation.
4235N/A *
4235N/A * This code is distributed in the hope that it will be useful, but WITHOUT
4235N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
4235N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
4235N/A * version 2 for more details (a copy is included in the LICENSE file that
4235N/A * accompanied this code).
4235N/A *
4235N/A * You should have received a copy of the GNU General Public License version
4235N/A * 2 along with this work; if not, write to the Free Software Foundation,
4235N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
4235N/A *
4235N/A * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
4235N/A * or visit www.oracle.com if you need additional information or have any
4235N/A * questions.
4235N/A */
4235N/A
4235N/A/*
4235N/A * @test
4235N/A * @bug 7036199
4235N/A * @summary Check that GarbageCollection notification are thrown by every GarbageCollectorMXBean
4235N/A * @author Frederic Parain
4235N/A * @run main/othervm GarbageCollectionNotificationTest
4235N/A */
4235N/A
4235N/Aimport java.util.*;
4235N/Aimport java.lang.management.*;
4235N/Aimport java.lang.reflect.*;
4235N/Aimport javax.management.*;
4235N/Aimport javax.management.openmbean.*;
4235N/Aimport com.sun.management.GarbageCollectionNotificationInfo;
4235N/Aimport com.sun.management.GcInfo;
4235N/Aimport java.security.AccessController;
4235N/Aimport java.security.PrivilegedAction;
4235N/Aimport java.lang.reflect.Field;
4235N/A
4235N/Apublic class GarbageCollectionNotificationTest {
4235N/A private static HashMap<String,Boolean> listenerInvoked = new HashMap<String,Boolean>();
4235N/A static volatile long count = 0;
4235N/A static volatile long number = 0;
4235N/A static Object synchronizer = new Object();
4235N/A
4235N/A static class GcListener implements NotificationListener {
4235N/A public void handleNotification(Notification notif, Object handback) {
4235N/A String type = notif.getType();
4235N/A if (type.equals(GarbageCollectionNotificationInfo.GARBAGE_COLLECTION_NOTIFICATION)) {
4235N/A GarbageCollectionNotificationInfo gcNotif =
4235N/A GarbageCollectionNotificationInfo.from((CompositeData) notif.getUserData());
4235N/A String source = ((ObjectName)notif.getSource()).getCanonicalName();
4235N/A synchronized(synchronizer) {
4235N/A if(!listenerInvoked.get(source)) {
4235N/A listenerInvoked.put(((ObjectName)notif.getSource()).getCanonicalName(),true);
4235N/A count++;
4235N/A if(count >= number) {
4235N/A synchronizer.notify();
4235N/A }
4235N/A }
4235N/A }
4235N/A }
4235N/A }
4235N/A }
4235N/A
4235N/A public static void main(String[] args) throws Exception {
4235N/A MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
4235N/A final Boolean isNotificationSupported = AccessController.doPrivileged (new PrivilegedAction<Boolean>() {
4235N/A public Boolean run() {
4235N/A try {
4235N/A Class cl = Class.forName("sun.management.VMManagementImpl");
4235N/A Field f = cl.getDeclaredField("gcNotificationSupport");
4235N/A f.setAccessible(true);
4235N/A return f.getBoolean(null);
4235N/A } catch(ClassNotFoundException e) {
4235N/A return false;
4235N/A } catch(NoSuchFieldException e) {
4235N/A return false;
4235N/A } catch(IllegalAccessException e) {
4235N/A return false;
4235N/A }
4235N/A }
4235N/A });
4235N/A if(!isNotificationSupported) {
4235N/A System.out.println("GC Notification not supported by the JVM, test skipped");
4235N/A return;
4235N/A }
4235N/A final ObjectName gcMXBeanPattern =
4235N/A new ObjectName("java.lang:type=GarbageCollector,*");
4235N/A Set<ObjectName> names =
4235N/A mbs.queryNames(gcMXBeanPattern, null);
4235N/A if (names.isEmpty())
4235N/A throw new Exception("Test incorrect: no GC MXBeans");
4235N/A number = names.size();
4235N/A for (ObjectName n : names) {
4235N/A if(mbs.isInstanceOf(n,"javax.management.NotificationEmitter")) {
4235N/A listenerInvoked.put(n.getCanonicalName(),false);
4235N/A GcListener listener = new GcListener();
4235N/A mbs.addNotificationListener(n, listener, null, null);
4235N/A }
4235N/A }
4235N/A // Invocation of System.gc() to trigger major GC
4235N/A System.gc();
4235N/A // Allocation of many short living and small objects to trigger minor GC
4235N/A Object data[] = new Object[32];
4235N/A for(int i = 0; i<100000000; i++) {
4235N/A data[i%32] = new int[8];
4235N/A }
4235N/A int wakeup = 0;
4235N/A synchronized(synchronizer) {
4235N/A while(count != number) {
4235N/A synchronizer.wait(10000);
4235N/A wakeup++;
4235N/A if(wakeup > 10)
4235N/A break;
4235N/A }
4235N/A }
4235N/A for (String source : listenerInvoked.keySet()) {
4235N/A if(!listenerInvoked.get(source))
4235N/A throw new Exception("Test incorrect: notifications have not been sent for "
4235N/A + source);
4235N/A }
4235N/A System.out.println("Test passed");
4235N/A }
4235N/A}