1/*
2 * Copyright (c) 2012, 2017, 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
24import java.io.EOFException;
25import java.io.File;
26import java.io.IOException;
27import java.lang.reflect.InvocationTargetException;
28import java.lang.reflect.Method;
29import java.net.BindException;
30import java.net.ConnectException;
31import java.net.ServerSocket;
32import java.rmi.RemoteException;
33import java.rmi.registry.LocateRegistry;
34import java.rmi.registry.Registry;
35import java.util.ArrayList;
36import java.util.Arrays;
37import java.util.List;
38import java.util.Objects;
39import java.util.Set;
40import java.util.concurrent.TimeoutException;
41import java.util.concurrent.atomic.AtomicBoolean;
42
43import javax.management.*;
44import javax.management.remote.*;
45import javax.net.ssl.SSLHandshakeException;
46
47import jdk.testlibrary.ProcessTools;
48import jdk.testlibrary.Utils;
49import jdk.internal.agent.Agent;
50import jdk.internal.agent.AgentConfigurationError;
51import jdk.internal.agent.ConnectorAddressLink;
52
53/**
54 * @test
55 * @bug 7110104
56 * @key randomness intermittent
57 * @summary Makes sure that enabling/disabling the management agent through JCMD
58 *          achieves the desired results
59 *
60 * @library /lib/testlibrary
61 * @modules java.management
62 *          java.rmi
63 *          jdk.management.agent/jdk.internal.agent
64 *
65 * @build jdk.testlibrary.* JMXStartStopTest PortAllocator TestApp ManagementAgentJcmd
66 * @run main/othervm/timeout=600 -XX:+UsePerfData JMXStartStopTest
67 */
68public class JMXStartStopTest {
69    private static final String TEST_APP_NAME = "TestApp";
70
71    private static final String TEST_SRC = System.getProperty("test.src");
72
73    private static final boolean verbose = false;
74
75    private static ManagementAgentJcmd jcmd = new ManagementAgentJcmd(TEST_APP_NAME, verbose);
76
77    private static void dbg_print(String msg) {
78        if (verbose) {
79            System.out.println("DBG: " + msg);
80        }
81    }
82
83    private static int listMBeans(MBeanServerConnection server,
84            ObjectName pattern,
85            QueryExp query)
86            throws Exception {
87
88        Set<ObjectName> names = server.queryNames(pattern,query);
89        for (ObjectName name : names) {
90            MBeanInfo info = server.getMBeanInfo(name);
91            dbg_print("Got MBean: " + name);
92
93            MBeanAttributeInfo[] attrs = info.getAttributes();
94            if (attrs == null)
95                continue;
96            for (MBeanAttributeInfo attr : attrs) {
97                if (attr.isReadable()) {
98                    server.getAttribute(name, attr.getName());
99                }
100            }
101        }
102        return names.size();
103    }
104
105    private static void testConnectLocal(long pid)
106            throws Exception {
107
108        String jmxUrlStr = null;
109
110        try {
111            jmxUrlStr = ConnectorAddressLink.importFrom((int)pid);
112            dbg_print("Local Service URL: " +jmxUrlStr);
113            if ( jmxUrlStr == null ) {
114                throw new Exception("No Service URL. Local agent not started?");
115            }
116
117            JMXServiceURL url = new JMXServiceURL(jmxUrlStr);
118
119            JMXConnector c = JMXConnectorFactory.connect(url, null);
120
121            MBeanServerConnection conn = c.getMBeanServerConnection();
122            ObjectName pattern = new ObjectName("java.lang:type=Memory,*");
123
124            int count = listMBeans(conn,pattern,null);
125            if (count == 0)
126                throw new Exception("Expected at least one matching "+
127                                    "MBean for "+pattern);
128
129        } catch (IOException e) {
130            dbg_print("Cannot find process : " + pid);
131            throw e;
132        }
133    }
134
135    private static void testNoConnect(int port) throws Exception {
136        testNoConnect(port, 0);
137    }
138
139    private static void testNoConnect(int port, int rmiPort) throws Exception {
140        try {
141            testConnect(port, rmiPort);
142            throw new Exception("Didn't expect the management agent running");
143        } catch (Exception e) {
144            Throwable t = e;
145            while (t != null) {
146                if (t instanceof RemoteException ||
147                    t instanceof SSLHandshakeException ||
148                    t instanceof ConnectException) {
149                    break;
150                }
151                t = t.getCause();
152            }
153            if (t == null) {
154                throw new Exception("Unexpected exception", e);
155            }
156        }
157    }
158
159    private static void testConnect(int port) throws Exception {
160        testConnect(port, 0);
161    }
162
163    private static void testConnect(int port, int rmiPort) throws Exception {
164        EOFException lastException = null;
165        // factor adjusted timeout (5 seconds) for the RMI to become available
166        long timeout = System.currentTimeMillis() + Utils.adjustTimeout(5000);
167        do {
168            try {
169                doTestConnect(port, rmiPort);
170                lastException = null;
171            } catch (EOFException e) {
172                lastException = e;
173                System.out.println("Error establishing RMI connection. Retrying in 500ms.");
174                Thread.sleep(500);
175            }
176        } while (lastException != null && System.currentTimeMillis() < timeout);
177
178        if (lastException != null) {
179            // didn't manage to get the RMI running in time
180            // rethrow the exception
181            throw lastException;
182        }
183    }
184
185    private static void doTestConnect(int port, int rmiPort) throws Exception {
186        dbg_print("RmiRegistry lookup...");
187
188        dbg_print("Using port: " + port);
189
190        dbg_print("Using rmi port: " + rmiPort);
191
192        Registry registry = LocateRegistry.getRegistry(port);
193
194        // "jmxrmi"
195        String[] relist = registry.list();
196        for (int i = 0; i < relist.length; ++i) {
197            dbg_print("Got registry: " + relist[i]);
198        }
199
200        String jmxUrlStr = (rmiPort != 0) ?
201            String.format(
202                        "service:jmx:rmi://localhost:%d/jndi/rmi://localhost:%d/jmxrmi",
203                        rmiPort,
204                port) :
205            String.format(
206                        "service:jmx:rmi:///jndi/rmi://localhost:%d/jmxrmi",
207                        port);
208
209        JMXServiceURL url = new JMXServiceURL(jmxUrlStr);
210
211        JMXConnector c = JMXConnectorFactory.connect(url, null);
212
213        MBeanServerConnection conn = c.getMBeanServerConnection();
214        ObjectName pattern = new ObjectName("java.lang:type=Memory,*");
215
216        int count = listMBeans(conn,pattern,null);
217        if (count == 0)
218            throw new Exception("Expected at least one matching " +
219                                "MBean for " + pattern);
220    }
221
222    private static class Failure {
223        private final Throwable cause;
224        private final String msg;
225
226        public Failure(Throwable cause, String msg) {
227            this.cause = cause;
228            this.msg = msg;
229        }
230
231        public Failure(String msg) {
232            this(null, msg);
233        }
234
235        public Throwable getCause() {
236            return cause;
237        }
238
239        public String getMsg() {
240            return msg;
241        }
242
243        @Override
244        public int hashCode() {
245            int hash = 7;
246            hash = 97 * hash + Objects.hashCode(this.cause);
247            hash = 97 * hash + Objects.hashCode(this.msg);
248            return hash;
249        }
250
251        @Override
252        public boolean equals(Object obj) {
253            if (obj == null) {
254                return false;
255            }
256            if (getClass() != obj.getClass()) {
257                return false;
258            }
259            final Failure other = (Failure) obj;
260            if (!Objects.equals(this.cause, other.cause)) {
261                return false;
262            }
263            if (!Objects.equals(this.msg, other.msg)) {
264                return false;
265            }
266            return true;
267        }
268
269        @Override
270        public String toString() {
271            if (cause != null) {
272                return msg + "\n" + cause;
273            } else {
274                return msg;
275            }
276        }
277    }
278
279    private static List<Failure> failures = new ArrayList<>();
280
281    public static void main(String args[]) throws Exception {
282        for (Method m : JMXStartStopTest.class.getDeclaredMethods()) {
283            if (m.getName().startsWith("test_")) {
284                long t1 = System.currentTimeMillis();
285                try {
286                    boolean retry = false;
287                    do {
288                        try {
289                            m.invoke(null);
290                            retry = false;
291                        } catch (InvocationTargetException e) {
292                            if (e.getCause() instanceof BindException ||
293                                e.getCause() instanceof java.rmi.ConnectException) {
294                                System.out.println("Failed to allocate ports. Retrying ...");
295                                retry = true;
296                            } else {
297                                throw e;
298                            }
299                        }
300                    } while (retry);
301                    System.out.println("=== PASSED");
302                } catch (Throwable e) {
303                    failures.add(new Failure(e, m.getName() + " failed"));
304                } finally {
305                    System.out.println("(took " + (System.currentTimeMillis() - t1) + "ms)\n");
306                }
307            }
308        }
309
310        if (!failures.isEmpty()) {
311            for(Failure f : failures) {
312                System.err.println(f.getMsg());
313                f.getCause().printStackTrace(System.err);
314            }
315            throw new Error();
316        }
317    }
318
319    private static class TestAppRun {
320        private Process p;
321        private final ProcessBuilder pb;
322        private final String name;
323        private final AtomicBoolean started = new AtomicBoolean(false);
324        private volatile long pid = -1;
325
326        public TestAppRun(ProcessBuilder pb, String name) {
327            this.pb = pb;
328            this.name = name;
329        }
330
331        public synchronized void start() throws InterruptedException, IOException, TimeoutException {
332            if (started.compareAndSet(false, true)) {
333                try {
334                    AtomicBoolean error = new AtomicBoolean(false);
335                    p = ProcessTools.startProcess(
336                            TEST_APP_NAME + "{" + name + "}",
337                            pb,
338                            (line) -> {
339                                boolean ok = line.equals("main enter");
340                                error.set(line.contains("BindException"));
341
342                                return ok || error.get();
343                            }
344                    );
345                    if (error.get()) {
346                        throw new BindException("Starting process failed due to " +
347                                                "the requested port not being available");
348                    }
349                    pid = p.pid();
350                } catch (TimeoutException e) {
351                    if (p != null) {
352                        p.destroy();
353                        p.waitFor();
354                    }
355                    throw e;
356                }
357            }
358        }
359
360        public long getPid() {
361            return pid;
362        }
363
364        public synchronized void stop()
365                throws IOException, InterruptedException {
366            if (started.compareAndSet(true, false)) {
367                p.getOutputStream().write(0);
368                p.getOutputStream().flush();
369                int ec = p.waitFor();
370                if (ec != 0) {
371                    StringBuilder msg = new StringBuilder();
372                    msg.append("Test application '").append(name);
373                    msg.append("' failed with exit code: ");
374                    msg.append(ec);
375
376                    failures.add(new Failure(msg.toString()));
377                }
378            }
379        }
380    }
381
382    /**
383     * Runs the test application "TestApp"
384     * @param name Test run name
385     * @param args Additional arguments
386     * @return Returns a {@linkplain TestAppRun} instance representing the run
387     * @throws IOException
388     * @throws InterruptedException
389     * @throws TimeoutException
390     */
391    private static TestAppRun doTest(String name, String ... args)
392            throws Exception {
393        List<String> pbArgs = new ArrayList<>(Arrays.asList(
394                "-cp",
395                System.getProperty("test.class.path"),
396                "-XX:+UsePerfData"
397        ));
398        pbArgs.addAll(Arrays.asList(args));
399        pbArgs.add(TEST_APP_NAME);
400
401        ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(
402                pbArgs.toArray(new String[pbArgs.size()])
403        );
404        TestAppRun s = new TestAppRun(pb, name);
405        s.start();
406        return s;
407    }
408
409    static void test_01() throws Exception {
410        // Run an app with JMX enabled stop it and
411        // restart on other port
412
413        System.out.println("**** Test one ****");
414        int ports[] = PortAllocator.allocatePorts(2);
415
416        TestAppRun s = doTest(
417                "test_01",
418                "-Dcom.sun.management.jmxremote.port=" + ports[0],
419                "-Dcom.sun.management.jmxremote.authenticate=false",
420                "-Dcom.sun.management.jmxremote.ssl=false");
421
422        try {
423            testConnect(ports[0]);
424
425            jcmd.stop();
426            testNoConnect(ports[0]);
427
428            jcmd.start("jmxremote.port=" + ports[1]);
429            testConnect(ports[1]);
430        } finally {
431            s.stop();
432        }
433    }
434
435    static void test_02() throws Exception {
436        // Run an app without JMX enabled
437        // start JMX by jcmd
438
439        System.out.println("**** Test two ****");
440
441        int[] ports = PortAllocator.allocatePorts(1);
442        TestAppRun s = doTest("test_02");
443        try {
444            jcmd.start(
445                "jmxremote.port=" + ports[0],
446                "jmxremote.authenticate=false",
447                "jmxremote.ssl=false"
448            );
449
450            testConnect(ports[0]);
451        } finally {
452//            debugPortUsage(pa);
453            s.stop();
454        }
455    }
456
457    static void test_03() throws Exception {
458        // Run an app without JMX enabled
459        // start JMX by jcmd on one port than on other one
460
461        System.out.println("**** Test three ****");
462
463        int[] ports = PortAllocator.allocatePorts(2);
464        TestAppRun s = doTest("test_03");
465        try {
466            jcmd.start(
467                "jmxremote.port=" + ports[0],
468                "jmxremote.authenticate=false",
469                "jmxremote.ssl=false"
470            );
471
472            // Second agent shouldn't start
473            jcmd.start(
474                "jmxremote.port=" + ports[1],
475                "jmxremote.authenticate=false",
476                "jmxremote.ssl=false"
477            );
478
479            // First agent should connect
480            testConnect(ports[0]);
481
482            // Second agent should not connect
483            testNoConnect(ports[1]);
484        } finally {
485            s.stop();
486        }
487    }
488
489    static void test_04() throws Exception {
490        // Run an app without JMX enabled
491        // start JMX by jcmd on one port, specify rmi port explicitly
492
493        System.out.println("**** Test four ****");
494
495        int[] ports = PortAllocator.allocatePorts(2);
496        TestAppRun s = doTest("test_04");
497        try {
498            jcmd.start(
499                "jmxremote.port=" + ports[0],
500                "jmxremote.rmi.port=" + ports[1],
501                "jmxremote.authenticate=false",
502                "jmxremote.ssl=false"
503            );
504
505            testConnect(ports[0], ports[1]);
506        } finally {
507            s.stop();
508        }
509    }
510
511    static void test_05() throws Exception {
512        // Run an app without JMX enabled, it will enable local server
513        // but should leave remote server disabled
514
515        System.out.println("**** Test five ****");
516        int[] ports = PortAllocator.allocatePorts(1);
517        TestAppRun s = doTest("test_05");
518        try {
519            jcmd.startLocal();
520
521            testNoConnect(ports[0]);
522            testConnectLocal(s.getPid());
523        } finally {
524            s.stop();
525        }
526    }
527
528    static void test_06() throws Exception {
529        // Run an app without JMX enabled
530        // start JMX by jcmd on one port, specify rmi port explicitly
531        // attempt to start it again with the same port
532        // Check for valid messages in the output
533
534        System.out.println("**** Test six ****");
535
536        int[] ports = PortAllocator.allocatePorts(2);
537        TestAppRun s = doTest("test_06");
538        try {
539            jcmd.start(
540                "jmxremote.port=" + ports[0],
541                "jmxremote.authenticate=false",
542                "jmxremote.ssl=false"
543            );
544
545            testConnect(ports[0], ports[1]);
546
547            final AtomicBoolean checks = new AtomicBoolean(false);
548            jcmd.start(
549                line -> {
550                    if (line.contains("java.lang.RuntimeException: Invalid agent state")) {
551                        checks.set(true);
552                    }
553                },
554                "jmxremote.port=" + ports[0],
555                "jmxremote.authenticate=false",
556                "jmxremote.ssl=false"
557            );
558
559            if (!checks.get()) {
560                throw new Exception("Starting agent on port " + ports[0] + " should "
561                        + "report an invalid agent state");
562            }
563        } finally {
564            s.stop();
565        }
566    }
567
568    static void test_07() throws Exception {
569        // Run an app without JMX enabled
570        // start JMX by jcmd on one port, specify rmi port explicitly
571        // attempt to start it again with other port
572        // Check for valid messages in the output
573
574        System.out.println("**** Test seven ****");
575
576        int[] ports = PortAllocator.allocatePorts(2);
577        TestAppRun s = doTest("test_07");
578        try {
579            jcmd.start(
580                "jmxremote.port=" + ports[0],
581                "jmxremote.authenticate=false",
582                "jmxremote.ssl=false"
583            );
584
585            testConnect(ports[0], ports[1]);
586
587            final AtomicBoolean checks = new AtomicBoolean(false);
588
589            jcmd.start(
590                line -> {
591                    if (line.contains("java.lang.RuntimeException: Invalid agent state")) {
592                        checks.set(true);
593                    }
594                },
595                "jmxremote.port=" + ports[1],
596                "jmxremote.authenticate=false",
597                "jmxremote.ssl=false"
598            );
599
600            if (!checks.get()) {
601                throw new Exception("Starting agent on poprt " + ports[1] + " should "
602                        + "report an invalid agent state");
603            }
604        } finally {
605            s.stop();
606        }
607    }
608
609    static void test_08() throws Exception {
610        // Run an app without JMX enabled
611        // start JMX by jcmd on one port, specify rmi port explicitly
612        // attempt to stop it twice
613        // Check for valid messages in the output
614
615        System.out.println("**** Test eight ****");
616
617        int[] ports = PortAllocator.allocatePorts(2);
618        TestAppRun s = doTest("test_08");
619        try {
620            jcmd.start(
621                "jmxremote.port=" + ports[0],
622                "jmxremote.authenticate=false",
623                "jmxremote.ssl=false"
624            );
625
626            testConnect(ports[0], ports[1]);
627
628            jcmd.stop();
629            jcmd.stop();
630        } finally {
631            s.stop();
632        }
633    }
634
635    static void test_09() throws Exception {
636        // Run an app without JMX enabled
637        // attempt to start JMX using a non-available port
638        // Check for valid messages in the output
639
640        System.out.println("**** Test nine ****");
641
642        TestAppRun s = doTest("test_09");
643
644        try (ServerSocket ss = new ServerSocket(0)) {
645            int localPort = ss.getLocalPort();
646            int[] ports;
647            do {
648                ports = PortAllocator.allocatePorts(1);
649            } while (localPort == ports[0]);
650
651            final AtomicBoolean checks = new AtomicBoolean(false);
652
653            int retryCntr = 1;
654            do {
655                final AtomicBoolean retry = new AtomicBoolean(false);
656
657                try {
658                    jcmd.start(
659                        line -> {
660                            if (line.contains(Agent.getText(AgentConfigurationError.AGENT_EXCEPTION))) {
661                                retry.set(true);
662                            }
663                        },
664                        "jmxremote.port=" + ports[0],
665                        "jmxremote.rmi.port=" + localPort,
666                        "jmxremote.authenticate=false",
667                        "jmxremote.ssl=false"
668                    );
669                } catch (BindException e) {
670                    checks.set(true);
671                }
672                if (!retry.get()) {
673                    break;
674                }
675                System.out.println("Attempt " + retryCntr + " >>>");
676                System.out.println("Unexpected reply from the agent. Retrying in 500ms ...");
677                Thread.sleep(500);
678            } while (retryCntr++ < 10);
679
680            if (!checks.get()) {
681                throw new Exception("Starting agent on port " + ports[0] + " should "
682                        + "report port in use");
683            }
684        } finally {
685            s.stop();
686        }
687
688    }
689
690    static void test_10() throws Exception {
691        // Run an app without JMX enabled, but with some properties set
692        // in command line.
693        // make sure these properties overridden corectly
694
695        System.out.println("**** Test ten ****");
696
697        int[] ports = PortAllocator.allocatePorts(2);
698        TestAppRun s = doTest(
699                "test_10",
700                "-Dcom.sun.management.jmxremote.authenticate=false",
701                "-Dcom.sun.management.jmxremote.ssl=true");
702
703        try {
704            testNoConnect(ports[0]);
705            jcmd.start(
706                "jmxremote.port=" + ports[1],
707                "jmxremote.authenticate=false",
708                "jmxremote.ssl=false"
709            );
710            testConnect(ports[1]);
711        } finally {
712            s.stop();
713        }
714    }
715
716    static void test_11() throws Exception {
717        // Run an app with JMX enabled and with some properties set
718        // in command line.
719        // stop JMX agent and then start it again with different property values
720        // make sure these properties overridden corectly
721
722        System.out.println("**** Test eleven ****");
723        int[] ports = PortAllocator.allocatePorts(2);
724        TestAppRun s = doTest(
725                "test_11",
726                "-Dcom.sun.management.jmxremote.port=" + ports[0],
727                "-Dcom.sun.management.jmxremote.authenticate=false",
728                "-Dcom.sun.management.jmxremote.ssl=true");
729
730        try {
731            testNoConnect(ports[0]);
732
733            jcmd.stop();
734
735            testNoConnect(ports[0]);
736
737            jcmd.start(
738                "jmxremote.port=" + ports[1],
739                "jmxremote.authenticate=false",
740                "jmxremote.ssl=false"
741            );
742
743            testConnect(ports[1]);
744        } finally {
745            s.stop();
746        }
747    }
748
749    static void test_12() throws Exception {
750        // Run an app with JMX enabled and with some properties set
751        // in command line.
752        // stop JMX agent and then start it again with different property values
753        // specifing some property in management config file and some of them
754        // in command line
755        // make sure these properties overridden corectly
756
757        System.out.println("**** Test twelve ****");
758
759        int[] ports = PortAllocator.allocatePorts(2);
760        TestAppRun s = doTest("test_12",
761                "-Dcom.sun.management.config.file="
762                + TEST_SRC + File.separator + "management_cl.properties",
763                "-Dcom.sun.management.jmxremote.authenticate=false"
764        );
765
766        try {
767            testNoConnect(ports[0]);
768
769            jcmd.stop();
770
771            testNoConnect(ports[0]);
772
773            jcmd.start(
774                "config.file=" + TEST_SRC + File.separator
775                + "management_jcmd.properties",
776                "jmxremote.authenticate=false",
777                "jmxremote.port=" + ports[1]
778            );
779
780            testConnect(ports[1]);
781        } finally {
782            s.stop();
783        }
784    }
785
786    static void test_13() throws Exception {
787        // Run an app with JMX enabled and with some properties set
788        // in command line.
789        // stop JMX agent and then start it again with different property values
790        // stop JMX agent again and then start it without property value
791        // make sure these properties overridden corectly
792
793        System.out.println("**** Test thirteen ****");
794        int[] ports = PortAllocator.allocatePorts(1);
795        TestAppRun s = doTest(
796                "test_13",
797                "-Dcom.sun.management.jmxremote.port=" + ports[0],
798                "-Dcom.sun.management.jmxremote.authenticate=false",
799                "-Dcom.sun.management.jmxremote.ssl=true");
800
801        try {
802            testNoConnect(ports[0]);
803
804            jcmd.stop();
805            jcmd.start(
806                "jmxremote.ssl=false",
807                "jmxremote.port=" + ports[0]
808            );
809            testConnect(ports[0]);
810
811            jcmd.stop();
812            jcmd.start(
813                "jmxremote.port=" + ports[0]
814            );
815
816            testNoConnect(ports[0]);
817        } finally {
818            s.stop();
819        }
820    }
821
822    static void test_14() throws Exception {
823        // Run an app with JMX enabled
824        // stop remote agent
825        // make sure local agent is not affected
826
827        System.out.println("**** Test fourteen ****");
828        int[] ports = PortAllocator.allocatePorts(1);
829        TestAppRun s = doTest(
830                "test_14",
831                "-Dcom.sun.management.jmxremote.port=" + ports[0],
832                "-Dcom.sun.management.jmxremote.authenticate=false",
833                "-Dcom.sun.management.jmxremote.ssl=false");
834        try {
835            testConnect(ports[0]);
836            jcmd.stop();
837            testConnectLocal(s.getPid());
838        } finally {
839            s.stop();
840        }
841    }
842
843    static void test_15() throws Exception {
844        // Run an app with JMX disabled
845        // start local agent only
846
847        System.out.println("**** Test fifteen ****");
848
849        int[] ports = PortAllocator.allocatePorts(1);
850        TestAppRun s = doTest("test_15");
851
852        try {
853            testNoConnect(ports[0]);
854            jcmd.startLocal();
855
856            testConnectLocal(s.getPid());
857
858        } finally {
859            s.stop();
860        }
861    }
862
863}
864