1 /*
   2  * Copyright 2004 Sun Microsystems, Inc.  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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
  20  * CA 95054 USA or visit www.sun.com if you need additional information or
  21  * have any questions.
  22  */
  23 
  24 /*
  25  * @test
  26  * @bug     5024531
  27  * @summary Test type mapping of the platform MXBean proxy
  28  *          returned from Management.newPlatformMXBeanProxy().
  29  * @author  Mandy Chung
  30  *
  31  * @compile -source 1.5 ProxyTypeMapping.java
  32  * @run main/othervm -verbose:gc ProxyTypeMapping
  33  */
  34 import java.lang.management.*;
  35 import javax.management.*;
  36 import static java.lang.management.ManagementFactory.*;
  37 import java.util.List;
  38 import java.util.Map;
  39 import java.util.Properties;
  40 import com.sun.management.GcInfo;
  41 
  42 public class ProxyTypeMapping {
  43     private static MBeanServer server =
  44         ManagementFactory.getPlatformMBeanServer();
  45     private static RuntimeMXBean runtime;
  46     private static ThreadMXBean thread;
  47     private static MemoryMXBean memory;
  48     private static MemoryPoolMXBean heapPool = null;
  49     private static MemoryPoolMXBean nonHeapPool = null;
  50     public static void main(String[] argv) throws Exception {
  51         runtime = newPlatformMXBeanProxy(server,
  52                                          RUNTIME_MXBEAN_NAME,
  53                                          RuntimeMXBean.class);
  54         thread = newPlatformMXBeanProxy(server,
  55                                         THREAD_MXBEAN_NAME,
  56                                         ThreadMXBean.class);
  57         memory = newPlatformMXBeanProxy(server,
  58                                         MEMORY_MXBEAN_NAME,
  59                                         MemoryMXBean.class);
  60 
  61         // check notification emitter
  62         MyListener listener = new MyListener();
  63         NotificationEmitter emitter = (NotificationEmitter) memory;
  64         emitter.addNotificationListener(listener, null, null);
  65         emitter.removeNotificationListener(listener);
  66 
  67         List<MemoryPoolMXBean> pools = getMemoryPoolMXBeans();
  68         for (MemoryPoolMXBean p : pools) {
  69             if (heapPool == null &&
  70                 p.getType() == MemoryType.HEAP &&
  71                 p.isUsageThresholdSupported() &&
  72                 p.isCollectionUsageThresholdSupported()) {
  73                 heapPool = p;
  74             }
  75             if (nonHeapPool == null &&
  76                 p.getType() == MemoryType.NON_HEAP &&
  77                 p.isUsageThresholdSupported()) {
  78                 nonHeapPool = p;
  79             }
  80         }
  81 
  82         checkEnum();
  83         checkList();
  84         checkMap();
  85         checkMemoryUsage();
  86         checkThreadInfo();
  87 
  88         checkOS();
  89         checkSunGC();
  90 
  91         System.out.println("Test passed.");
  92     }
  93 
  94     private static void checkEnum() throws Exception {
  95         MemoryType type = heapPool.getType();
  96         if (type != MemoryType.HEAP) {
  97             throw new RuntimeException("TEST FAILED: " +
  98                 " incorrect memory type for " + heapPool.getName());
  99         }
 100 
 101         type = nonHeapPool.getType();
 102         if (type != MemoryType.NON_HEAP) {
 103             throw new RuntimeException("TEST FAILED: " +
 104                 " incorrect memory type for " + nonHeapPool.getName());
 105         }
 106     }
 107 
 108     private static final String OPTION = "-verbose:gc";
 109     private static void checkList() throws Exception {
 110         List<String> args = runtime.getInputArguments();
 111         if (args.size() < 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         Map<String,String> props1 = runtime.getSystemProperties();
 140         String value1 = props1.get(KEY1);
 141         if (value1 == null || !value1.equals(VALUE1)) {
 142             throw new RuntimeException("TEST FAILED: " +
 143                  KEY1 + " property found" +
 144                  " with value = " + value1 +
 145                  " but expected to be " + VALUE1);
 146         }
 147 
 148         String value2 = props1.get(KEY2);
 149         if (value2 == null || !value2.equals(VALUE2)) {
 150             throw new RuntimeException("TEST FAILED: " +
 151                  KEY2 + " property found" +
 152                  " with value = " + value2 +
 153                  " but expected to be " + VALUE2);
 154         }
 155 
 156         String value3 = props1.get(KEY3);
 157         if (value3 != null) {
 158             throw new RuntimeException("TEST FAILED: " +
 159                  KEY3 + " property found" +
 160                  " but should not exist" );
 161         }
 162     }
 163 
 164     private static void checkMemoryUsage() throws Exception {
 165         // sanity check to have non-zero usage
 166         MemoryUsage u1 = memory.getHeapMemoryUsage();
 167         MemoryUsage u2 = memory.getNonHeapMemoryUsage();
 168         MemoryUsage u3 = heapPool.getUsage();
 169         MemoryUsage u4 = nonHeapPool.getUsage();
 170         if (u1.getCommitted() <= 0 ||
 171             u2.getCommitted() <= 0 ||
 172             u3.getCommitted() <= 0 ||
 173             u4.getCommitted() <= 0) {
 174             throw new RuntimeException("TEST FAILED: " +
 175                 " expected non-zero committed usage");
 176         }
 177         memory.gc();
 178         MemoryUsage u5 = heapPool.getCollectionUsage();
 179         if (u5.getCommitted() <= 0) {
 180             throw new RuntimeException("TEST FAILED: " +
 181                 " expected non-zero committed collected usage");
 182         }
 183     }
 184 
 185     private static void checkThreadInfo() throws Exception {
 186         // assume all threads stay alive
 187         long[] ids = thread.getAllThreadIds();
 188         ThreadInfo[] infos = thread.getThreadInfo(ids);
 189         for (ThreadInfo ti : infos) {
 190             printThreadInfo(ti);
 191         }
 192         infos = thread.getThreadInfo(ids, 2);
 193         for (ThreadInfo ti : infos) {
 194             printThreadInfo(ti);
 195         }
 196         long id = Thread.currentThread().getId();
 197         ThreadInfo info = thread.getThreadInfo(id);
 198         printThreadInfo(info);
 199         info = thread.getThreadInfo(id, 2);
 200         printThreadInfo(info);
 201     }
 202 
 203     private static void printThreadInfo(ThreadInfo info) {
 204         if (info == null) {
 205             throw new RuntimeException("TEST FAILED: " +
 206                 " Null ThreadInfo");
 207         }
 208 
 209         System.out.print(info.getThreadName());
 210         System.out.print(" id=" + info.getThreadId());
 211         System.out.println(" " + info.getThreadState());
 212 
 213         for (StackTraceElement s : info.getStackTrace()) {
 214             System.out.println(s);
 215         }
 216     }
 217 
 218     private static void checkOS() throws Exception {
 219         com.sun.management.OperatingSystemMXBean os =
 220             newPlatformMXBeanProxy(server,
 221                                    OPERATING_SYSTEM_MXBEAN_NAME,
 222                                    com.sun.management.OperatingSystemMXBean.class);
 223         System.out.println("# CPUs = " + os.getAvailableProcessors());
 224         System.out.println("Committed virtual memory = " +
 225                            os.getCommittedVirtualMemorySize());
 226     }
 227 
 228     private static void checkSunGC() throws Exception {
 229         // Test com.sun.management proxy
 230         List<GarbageCollectorMXBean> gcs = getGarbageCollectorMXBeans();
 231         for (GarbageCollectorMXBean gc : gcs) {
 232             com.sun.management.GarbageCollectorMXBean sunGc =
 233                newPlatformMXBeanProxy(server,
 234                    GARBAGE_COLLECTOR_MXBEAN_DOMAIN_TYPE + ",name=" + gc.getName(),
 235                    com.sun.management.GarbageCollectorMXBean.class);
 236             GcInfo info = sunGc.getLastGcInfo();
 237             if (info != null) {
 238                 System.out.println("GC statistic for : " + gc.getName());
 239                 printGcInfo(info);
 240             }
 241         }
 242     }
 243     private static void printGcInfo(GcInfo info) throws Exception {
 244         System.out.print("GC #" + info.getId());
 245         System.out.print(" start:" + info.getStartTime());
 246         System.out.print(" end:" + info.getEndTime());
 247         System.out.println(" (" + info.getDuration() + "ms)");
 248         Map<String,MemoryUsage> usage = info.getMemoryUsageBeforeGc();
 249 
 250         for (Map.Entry<String,MemoryUsage> entry : usage.entrySet()) {
 251             String poolname = entry.getKey();
 252             MemoryUsage busage = entry.getValue();
 253             MemoryUsage ausage = info.getMemoryUsageAfterGc().get(poolname);
 254             if (ausage == null) {
 255                 throw new RuntimeException("After Gc Memory does not exist" +
 256                     " for " + poolname);
 257             }
 258             System.out.println("Usage for pool " + poolname);
 259             System.out.println("   Before GC: " + busage);
 260             System.out.println("   After GC: " + ausage);
 261         }
 262     }
 263 
 264     static class MyListener implements NotificationListener {
 265         public void handleNotification(Notification notif, Object handback) {
 266             return;
 267         }
 268     }
 269 }