1/* 2 * Copyright (c) 2004, 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 5024531 27 * @summary Validate open types mapped for the MXBeans in the platform 28 * MBeanServer. 29 * @author Mandy Chung 30 * 31 * @compile ValidateOpenTypes.java 32 * @run main/othervm -verbose:gc ValidateOpenTypes 33 */ 34import java.lang.management.*; 35import javax.management.*; 36import javax.management.openmbean.CompositeData; 37import javax.management.openmbean.TabularData; 38import static java.lang.management.ManagementFactory.*; 39import java.util.List; 40import java.util.Map; 41import com.sun.management.GcInfo; 42 43public class ValidateOpenTypes { 44 private static MBeanServer server = 45 ManagementFactory.getPlatformMBeanServer(); 46 private static ObjectName memory; 47 private static ObjectName thread; 48 private static ObjectName runtime; 49 private static ObjectName os; 50 private static ObjectName heapPool = null; 51 private static ObjectName nonHeapPool = null; 52 53 public static void main(String[] argv) throws Exception { 54 memory = new ObjectName(MEMORY_MXBEAN_NAME); 55 runtime = new ObjectName(RUNTIME_MXBEAN_NAME); 56 thread = new ObjectName(THREAD_MXBEAN_NAME); 57 os = new ObjectName(OPERATING_SYSTEM_MXBEAN_NAME); 58 59 List<MemoryPoolMXBean> pools = getMemoryPoolMXBeans(); 60 for (MemoryPoolMXBean p : pools) { 61 if (heapPool == null && 62 p.getType() == MemoryType.HEAP && 63 p.isUsageThresholdSupported() && 64 p.isCollectionUsageThresholdSupported()) { 65 heapPool = new ObjectName(MEMORY_POOL_MXBEAN_DOMAIN_TYPE + 66 ",name=" + p.getName()); 67 } 68 if (nonHeapPool == null && 69 p.getType() == MemoryType.NON_HEAP && 70 p.isUsageThresholdSupported()) { 71 nonHeapPool = new ObjectName(MEMORY_POOL_MXBEAN_DOMAIN_TYPE + 72 ",name=" + p.getName()); 73 } 74 } 75 76 // Check notification emitters 77 MyListener listener = new MyListener(); 78 server.addNotificationListener(memory, listener, null, null); 79 server.removeNotificationListener(memory, listener); 80 81 checkEnum(); 82 checkList(); 83 checkMap(); 84 checkMemoryUsage(); 85 checkThreadInfo(); 86 87 checkOS(); 88 checkSunGC(); 89 90 System.out.println("Test passed."); 91 } 92 93 private static void checkEnum() throws Exception { 94 String type = (String) server.getAttribute(heapPool, "Type"); 95 if (!type.equals("HEAP")) { 96 throw new RuntimeException("TEST FAILED: " + 97 " incorrect memory type for " + heapPool); 98 } 99 100 type = (String) server.getAttribute(nonHeapPool, "Type"); 101 if (!type.equals("NON_HEAP")) { 102 throw new RuntimeException("TEST FAILED: " + 103 " incorrect memory type for " + nonHeapPool); 104 } 105 } 106 107 private static final String OPTION = "-verbose:gc"; 108 private static void checkList() throws Exception { 109 String[] args = (String[]) server.getAttribute(runtime, 110 "InputArguments"); 111 if (args.length < 1) { 112 throw new RuntimeException("TEST FAILED: " + 113 " empty input arguments"); 114 } 115 // check if -verbose:gc exists 116 boolean found = false; 117 for (String option : args) { 118 if (option.equals(OPTION)) { 119 found = true; 120 break; 121 } 122 } 123 if (!found) { 124 throw new RuntimeException("TEST FAILED: " + 125 "VM option " + OPTION + " not found"); 126 } 127 } 128 129 private static final String KEY1 = "test.property.key1"; 130 private static final String VALUE1 = "test.property.value1"; 131 private static final String KEY2 = "test.property.key2"; 132 private static final String VALUE2 = "test.property.value2"; 133 private static final String KEY3 = "test.property.key3"; 134 private static void checkMap() throws Exception { 135 // Add new system properties 136 System.setProperty(KEY1, VALUE1); 137 System.setProperty(KEY2, VALUE2); 138 139 TabularData props1 = (TabularData) 140 server.getAttribute(runtime, "SystemProperties"); 141 142 String value1 = getProperty(props1, KEY1); 143 if (value1 == null || !value1.equals(VALUE1)) { 144 throw new RuntimeException("TEST FAILED: " + 145 KEY1 + " property found" + 146 " with value = " + value1 + 147 " but expected to be " + VALUE1); 148 } 149 150 String value2 = getProperty(props1, KEY2); 151 if (value2 == null || !value2.equals(VALUE2)) { 152 throw new RuntimeException("TEST FAILED: " + 153 KEY2 + " property found" + 154 " with value = " + value2 + 155 " but expected to be " + VALUE2); 156 } 157 158 String value3 = getProperty(props1, KEY3); 159 if (value3 != null) { 160 throw new RuntimeException("TEST FAILED: " + 161 KEY3 + " property found" + 162 " but should not exist" ); 163 } 164 } 165 private static String getProperty(TabularData td, String propName) { 166 CompositeData cd = td.get(new Object[] { propName}); 167 if (cd != null) { 168 String key = (String) cd.get("key"); 169 if (!propName.equals(key)) { 170 throw new RuntimeException("TEST FAILED: " + 171 key + " property found" + 172 " but expected to be " + propName); 173 } 174 return (String) cd.get("value"); 175 } 176 return null; 177 } 178 179 private static void checkMemoryUsage() throws Exception { 180 // sanity check to have non-negative usage 181 Object u1 = server.getAttribute(memory, "HeapMemoryUsage"); 182 Object u2 = server.getAttribute(memory, "NonHeapMemoryUsage"); 183 Object u3 = server.getAttribute(heapPool, "Usage"); 184 Object u4 = server.getAttribute(nonHeapPool, "Usage"); 185 if (getCommitted(u1) < 0 || 186 getCommitted(u2) < 0 || 187 getCommitted(u3) < 0 || 188 getCommitted(u4) < 0) { 189 throw new RuntimeException("TEST FAILED: " + 190 " expected non-negative committed usage"); 191 } 192 server.invoke(memory, "gc", new Object[0], new String[0]); 193 Object u5 = server.getAttribute(heapPool, "CollectionUsage"); 194 if (getCommitted(u5) < 0) { 195 throw new RuntimeException("TEST FAILED: " + 196 " expected non-negative committed collected usage"); 197 } 198 } 199 200 private static long getCommitted(Object data) { 201 MemoryUsage u = MemoryUsage.from((CompositeData) data); 202 return u.getCommitted(); 203 } 204 205 private static void checkThreadInfo() throws Exception { 206 // assume all threads stay alive 207 long[] ids = (long[]) server.getAttribute(thread, "AllThreadIds"); 208 Object result = server.invoke(thread, 209 "getThreadInfo", 210 new Object[] { ids }, 211 new String[] { "[J" }); 212 for (CompositeData cd : (CompositeData[]) result) { 213 printThreadInfo(cd); 214 } 215 216 result = server.invoke(thread, 217 "getThreadInfo", 218 new Object[] { ids, new Integer(2) }, 219 new String[] { "[J", "int" }); 220 for (CompositeData cd : (CompositeData[]) result) { 221 printThreadInfo(cd); 222 } 223 224 long id = Thread.currentThread().getId(); 225 result = server.invoke(thread, 226 "getThreadInfo", 227 new Object[] { new Long(id) }, 228 new String[] { "long" }); 229 printThreadInfo((CompositeData) result); 230 231 result = server.invoke(thread, 232 "getThreadInfo", 233 new Object[] { new Long(id), new Integer(2) }, 234 new String[] { "long", "int" }); 235 printThreadInfo((CompositeData) result); 236 } 237 238 private static void printThreadInfo(CompositeData cd) { 239 ThreadInfo info = ThreadInfo.from(cd); 240 if (info == null) { 241 throw new RuntimeException("TEST FAILED: " + 242 " Null ThreadInfo"); 243 } 244 245 System.out.print(info.getThreadName()); 246 System.out.print(" id=" + info.getThreadId()); 247 System.out.println(" " + info.getThreadState()); 248 249 for (StackTraceElement s : info.getStackTrace()) { 250 System.out.println(s); 251 } 252 } 253 254 private static void checkOS() throws Exception { 255 Integer cpus = (Integer) server.getAttribute(os, "AvailableProcessors"); 256 System.out.println("# CPUs = " + cpus); 257 Long vmem = (Long) server.getAttribute(os, "CommittedVirtualMemorySize"); 258 System.out.println("Committed virtual memory = " + vmem); 259 } 260 261 private static void checkSunGC() throws Exception { 262 // Test com.sun.management proxy 263 List<GarbageCollectorMXBean> gcs = getGarbageCollectorMXBeans(); 264 for (GarbageCollectorMXBean gc : gcs) { 265 ObjectName sunGc = 266 new ObjectName(GARBAGE_COLLECTOR_MXBEAN_DOMAIN_TYPE + 267 ",name=" + gc.getName()); 268 CompositeData cd = (CompositeData) server.getAttribute(sunGc, "LastGcInfo"); 269 if (cd != null) { 270 System.out.println("GC statistic for : " + gc.getName()); 271 printGcInfo(cd); 272 } 273 } 274 } 275 276 private static void printGcInfo(CompositeData cd) throws Exception { 277 GcInfo info = GcInfo.from(cd); 278 System.out.print("GC #" + info.getId()); 279 System.out.print(" start:" + info.getStartTime()); 280 System.out.print(" end:" + info.getEndTime()); 281 System.out.println(" (" + info.getDuration() + "ms)"); 282 Map<String,MemoryUsage> usage = info.getMemoryUsageBeforeGc(); 283 284 for (Map.Entry<String,MemoryUsage> entry : usage.entrySet()) { 285 String poolname = entry.getKey(); 286 MemoryUsage busage = entry.getValue(); 287 MemoryUsage ausage = info.getMemoryUsageAfterGc().get(poolname); 288 if (ausage == null) { 289 throw new RuntimeException("After Gc Memory does not exist" + 290 " for " + poolname); 291 } 292 System.out.println("Usage for pool " + poolname); 293 System.out.println(" Before GC: " + busage); 294 System.out.println(" After GC: " + ausage); 295 } 296 } 297 298 static class MyListener implements NotificationListener { 299 public void handleNotification(Notification notif, Object handback) { 300 return; 301 } 302 } 303} 304