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