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