1 /* 2 * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24 /* 25 * @test 26 * @bug 7036199 27 * @summary Check that GarbageCollection notification are thrown by every GarbageCollectorMXBean 28 * @author Frederic Parain 29 * @requires vm.opt.ExplicitGCInvokesConcurrent == null | vm.opt.ExplicitGCInvokesConcurrent == false 30 * @modules java.management/sun.management 31 * jdk.management 32 * @run main/othervm GarbageCollectionNotificationTest 33 */ 34 35 import java.util.*; 36 import java.lang.management.*; 37 import java.lang.reflect.*; 38 import javax.management.*; 39 import javax.management.openmbean.*; 40 import com.sun.management.GarbageCollectionNotificationInfo; 41 import com.sun.management.GcInfo; 42 import java.security.AccessController; 43 import java.security.PrivilegedAction; 44 import java.lang.reflect.Field; 45 46 public class GarbageCollectionNotificationTest { 47 private static HashMap<String,Boolean> listenerInvoked = new HashMap<String,Boolean>(); 48 static volatile long count = 0; 49 static volatile long number = 0; 50 static Object synchronizer = new Object(); 51 52 static class GcListener implements NotificationListener { 53 public void handleNotification(Notification notif, Object handback) { 54 String type = notif.getType(); 55 if (type.equals(GarbageCollectionNotificationInfo.GARBAGE_COLLECTION_NOTIFICATION)) { 56 GarbageCollectionNotificationInfo gcNotif = 57 GarbageCollectionNotificationInfo.from((CompositeData) notif.getUserData()); 58 String source = ((ObjectName)notif.getSource()).getCanonicalName(); 59 synchronized(synchronizer) { 60 if(!listenerInvoked.get(source)) { 61 listenerInvoked.put(((ObjectName)notif.getSource()).getCanonicalName(),true); 62 count++; 63 if(count >= number) { 64 synchronizer.notify(); 65 } 66 } 67 } 68 } 69 } 70 } 71 72 public static void main(String[] args) throws Exception { 73 MBeanServer mbs = ManagementFactory.getPlatformMBeanServer(); 74 final boolean isNotificationSupported = 75 sun.management.ManagementFactoryHelper.getVMManagement().isGcNotificationSupported(); 76 77 if(!isNotificationSupported) { 78 System.out.println("GC Notification not supported by the JVM, test skipped"); 79 return; 80 } 81 final ObjectName gcMXBeanPattern = 82 new ObjectName("java.lang:type=GarbageCollector,*"); 83 Set<ObjectName> names = 84 mbs.queryNames(gcMXBeanPattern, null); 85 if (names.isEmpty()) 86 throw new Exception("Test incorrect: no GC MXBeans"); 87 number = names.size(); 88 for (ObjectName n : names) { 89 if(mbs.isInstanceOf(n,"javax.management.NotificationEmitter")) { 90 listenerInvoked.put(n.getCanonicalName(),false); 91 GcListener listener = new GcListener(); 92 mbs.addNotificationListener(n, listener, null, null); 93 } 94 } 95 // Invocation of System.gc() to trigger major GC 96 System.gc(); 97 // Allocation of many short living and small objects to trigger minor GC 98 Object data[] = new Object[32]; 99 for(int i = 0; i<100000000; i++) { 100 data[i%32] = new int[8]; 101 } 102 int wakeup = 0; 103 synchronized(synchronizer) { 104 while(count != number) { 105 synchronizer.wait(10000); 106 wakeup++; 107 if(wakeup > 10) 108 break; 109 } 110 } 111 for (String source : listenerInvoked.keySet()) { 112 if(!listenerInvoked.get(source)) 113 throw new Exception("Test incorrect: notifications have not been sent for " 114 + source); 115 } 116 System.out.println("Test passed"); 117 } 118 }