DaemonRMIExporterTest.java revision 16603:db6e995edd0a
1/*
2 * Copyright (c) 2003, 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/*
26 * @test
27 * @bug 6760712
28 * @summary test the connector server option that causes it not to prevent the
29 * VM from exiting
30 * @author Shanliang JIANG, Eamonn McManus
31 * @modules java.management.rmi
32 * @run main/othervm DaemonRMIExporterTest
33 */
34import java.util.Arrays;
35import java.util.Collections;
36import java.util.HashSet;
37import java.util.Map;
38import java.util.Set;
39
40import javax.management.MBeanServerFactory;
41import javax.management.remote.JMXConnector;
42import javax.management.remote.JMXConnectorFactory;
43import javax.management.remote.JMXServiceURL;
44import javax.management.remote.JMXConnectorServer;
45import javax.management.remote.JMXConnectorServerFactory;
46
47// Test the connector server option that causes it not to prevent the VM
48// from exiting.  It's tricky to test exactly that, though possible.  If
49// we're being run from within jtreg, then jtreg has threads of its own
50// that will prevent the VM from exiting.  What's more it will kill all
51// threads that the test created as soon as the main method returns,
52// including the ones that would prevent the VM from exiting without the
53// special option.
54// Here we check that the test code does not create
55// any permanent non-daemon threads, by recording the initial set of
56// non-daemon threads (including at least one from jtreg), doing our stuff,
57// then waiting for there to be no non-daemon threads that were not in
58// the initial set.
59public class DaemonRMIExporterTest {
60    public static void main(String[] args) throws Exception {
61        Set<Thread> initialNonDaemonThreads = getNonDaemonThreads();
62
63        JMXServiceURL addr = new JMXServiceURL("rmi", null, 0);
64        System.out.println("DaemonRMIExporterTest: Creating a RMIConnectorServer on " + addr);
65        Map<String, ?> env =
66            Collections.singletonMap("jmx.remote.x.daemon", "true");
67        JMXConnectorServer server =
68                JMXConnectorServerFactory.newJMXConnectorServer(addr,
69                env,
70                MBeanServerFactory.createMBeanServer());
71        server.start();
72        System.out.println("DaemonRMIExporterTest: Started the server on " + server.getAddress());
73
74        System.out.println("DaemonRMIExporterTest: Connecting a client to the server ...");
75        final JMXConnector conn = JMXConnectorFactory.connect(server.getAddress());
76        conn.getMBeanServerConnection().getDefaultDomain();
77
78        System.out.println("DaemonRMIExporterTest: Closing the client ...");
79        conn.close();
80
81        System.out.println("DaemonRMIExporterTest No more user code to execute, the VM should " +
82                "exit normally, otherwise will be blocked forever if the bug is not fixed.");
83
84        long deadline = System.currentTimeMillis() + 10000;
85        ok: {
86            while (System.currentTimeMillis() < deadline) {
87                Set<Thread> nonDaemonThreads = getNonDaemonThreads();
88                nonDaemonThreads.removeAll(initialNonDaemonThreads);
89                if (nonDaemonThreads.isEmpty())
90                    break ok;
91                System.out.println("Non-daemon threads: " + nonDaemonThreads);
92                try {
93                    Thread.sleep(500);
94                } catch (InterruptedException e) {
95                    throw new AssertionError(e);
96                }
97            }
98            throw new Exception("TEST FAILED: non-daemon threads remain");
99        }
100
101        System.out.println("TEST PASSED");
102    }
103
104    private static Set<Thread> getNonDaemonThreads() {
105        ThreadGroup tg = Thread.currentThread().getThreadGroup();
106        while (tg.getParent() != null)
107            tg = tg.getParent();
108        Thread[] threads = null;
109        for (int size = 10; size < 10000; size *= 2) {
110            threads = new Thread[size];
111            int n = tg.enumerate(threads, true);
112            if (n < size) {
113                threads = Arrays.copyOf(threads, n);
114                break;
115            }
116        }
117        Set<Thread> ndThreads = new HashSet<Thread>();
118        for (Thread t : threads) {
119            if (!t.isDaemon())
120                ndThreads.add(t);
121        }
122        return ndThreads;
123    }
124}
125