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;
main(String[] argv)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 
checkEnum()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";
checkList()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";
checkMap()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 
checkMemoryUsage()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 
checkThreadInfo()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 
printThreadInfo(ThreadInfo info)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 
checkOS()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 
checkSunGC()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     }
printGcInfo(GcInfo info)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 {
handleNotification(Notification notif, Object handback)264         public void handleNotification(Notification notif, Object handback) {
265             return;
266         }
267     }
268 }
269