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 * 30 * @requires vm.opt.ExplicitGCInvokesConcurrent == null | vm.opt.ExplicitGCInvokesConcurrent == false 31 * @modules java.management/sun.management 32 * jdk.management 33 * 34 * @run main/othervm GarbageCollectionNotificationTest 35 */ 36 37 import java.util.*; 38 import java.lang.management.*; 39 import java.lang.reflect.*; 40 import javax.management.*; 41 import javax.management.openmbean.*; 42 import com.sun.management.GarbageCollectionNotificationInfo; 43 import com.sun.management.GcInfo; 44 import java.security.AccessController; 45 import java.security.PrivilegedAction; 46 import java.lang.reflect.Field; 47 48 public class GarbageCollectionNotificationTest { 49 private static HashMap<String,Boolean> listenerInvoked = new HashMap<String,Boolean>(); 50 static volatile long count = 0; 51 static volatile long number = 0; 52 static Object synchronizer = new Object(); 53 54 static class GcListener implements NotificationListener { 55 public void handleNotification(Notification notif, Object handback) { 56 String type = notif.getType(); 57 if (type.equals(GarbageCollectionNotificationInfo.GARBAGE_COLLECTION_NOTIFICATION)) { 58 GarbageCollectionNotificationInfo gcNotif = 59 GarbageCollectionNotificationInfo.from((CompositeData) notif.getUserData()); 60 String source = ((ObjectName)notif.getSource()).getCanonicalName(); 61 synchronized(synchronizer) { 62 if(!listenerInvoked.get(source)) { 63 listenerInvoked.put(((ObjectName)notif.getSource()).getCanonicalName(),true); 64 count++; 65 if(count >= number) { 66 synchronizer.notify(); 67 } 68 } 69 } 70 } 71 } 72 } 73 74 public static void main(String[] args) throws Exception { 75 MBeanServer mbs = ManagementFactory.getPlatformMBeanServer(); 76 final boolean isNotificationSupported = 77 sun.management.ManagementFactoryHelper.getVMManagement().isGcNotificationSupported(); 78 79 if(!isNotificationSupported) { 80 System.out.println("GC Notification not supported by the JVM, test skipped"); 81 return; 82 } 83 final ObjectName gcMXBeanPattern = 84 new ObjectName("java.lang:type=GarbageCollector,*"); 85 Set<ObjectName> names = 86 mbs.queryNames(gcMXBeanPattern, null); 87 if (names.isEmpty()) 88 throw new Exception("Test incorrect: no GC MXBeans"); 89 number = names.size(); 90 for (ObjectName n : names) { 91 if(mbs.isInstanceOf(n,"javax.management.NotificationEmitter")) { 92 listenerInvoked.put(n.getCanonicalName(),false); 93 GcListener listener = new GcListener(); 94 mbs.addNotificationListener(n, listener, null, null); 95 } 96 } 97 // Invocation of System.gc() to trigger major GC 98 System.gc(); 99 // Allocation of many short living and small objects to trigger minor GC 100 Object data[] = new Object[32]; 101 for(int i = 0; i<100000000; i++) { 102 data[i%32] = new int[8]; 103 } 104 int wakeup = 0; 105 synchronized(synchronizer) { 106 while(count != number) { 107 synchronizer.wait(10000); 108 wakeup++; 109 if(wakeup > 10) 110 break; 111 } 112 } 113 for (String source : listenerInvoked.keySet()) { 114 if(!listenerInvoked.get(source)) 115 throw new Exception("Test incorrect: notifications have not been sent for " 116 + source); 117 } 118 System.out.println("Test passed"); 119 } 120 }