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