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