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