test/sun/management/jmxremote/startstop/JMXStartStopTest.java

Print this page
rev 10063 : [mq]: startManagmentAgent

  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 import java.io.File;
  25 import java.io.IOException;
  26 import java.lang.reflect.Method;
  27 import java.net.ConnectException;
  28 import java.net.ServerSocket;
  29 import java.rmi.NoSuchObjectException;
  30 import java.rmi.registry.LocateRegistry;
  31 import java.rmi.registry.Registry;
  32 import java.util.ArrayList;
  33 import java.util.Arrays;
  34 import java.util.HashMap;
  35 import java.util.Iterator;
  36 import java.util.List;
  37 import java.util.Map;
  38 import java.util.Objects;
  39 import java.util.Set;
  40 import java.util.concurrent.TimeUnit;
  41 import java.util.concurrent.TimeoutException;
  42 import java.util.concurrent.atomic.AtomicBoolean;
  43 import java.util.concurrent.atomic.AtomicReference;
  44 import java.util.function.Consumer;
  45 
  46 import javax.management.*;
  47 import javax.management.remote.*;
  48 import javax.net.ssl.SSLHandshakeException;
  49 
  50 import jdk.testlibrary.ProcessTools;
  51 import jdk.testlibrary.JDKToolLauncher;
  52 
  53 /**
  54  * @test
  55  * @bug 7110104
  56  * @library /lib/testlibrary
  57  * @build jdk.testlibrary.* JMXStartStopTest JMXStartStopDoSomething
  58  * @run main/othervm JMXStartStopTest
  59  * @summary Makes sure that enabling/disabling the management agent through
  60  *          JCMD achieves the desired results
  61  */
  62 public class JMXStartStopTest {
  63     private static final String TEST_JDK = System.getProperty("test.jdk");
  64     private static final String TEST_SRC = System.getProperty("test.src");
  65 
  66     private static final boolean verbose = false;
  67 
  68     /**
  69      * Dynamically allocates two distinct ports using {@linkplain java.net.ServerSocket}
  70      * It keeps each of those ports blocked until it is first accessed by its getter
  71      */
  72     private static class PortAllocator {
  73         private final int port1, port2;
  74         private final ServerSocket ss1, ss2;
  75         PortAllocator() {
  76             try {
  77                 ss1 = new ServerSocket(0);
  78                 ss2 = new ServerSocket(0);
  79                 port1 = ss1.getLocalPort();
  80                 port2 = ss2.getLocalPort();
  81             } catch (IOException e) {
  82                 throw new Error("Error while obtaining free ports", e);
  83             }


 100                     ss2.close();
 101                 } catch (IOException e) {
 102                     // just ignore
 103                 }
 104             }
 105             return port2;
 106         }
 107     }
 108 
 109     private static void dbg_print(String msg){
 110         if (verbose) {
 111             System.out.println("DBG: " +msg);
 112         }
 113     }
 114 
 115     private static int listMBeans(MBeanServerConnection server,
 116                                   ObjectName pattern,
 117                                   QueryExp query)
 118     throws Exception {
 119 
 120         Set names = server.queryNames(pattern,query);
 121         for (Iterator i=names.iterator(); i.hasNext(); ) {
 122             ObjectName name = (ObjectName)i.next();
 123             MBeanInfo info = server.getMBeanInfo(name);
 124             dbg_print("Got MBean: " + name);
 125 
 126             MBeanAttributeInfo[] attrs = info.getAttributes();
 127             if (attrs == null)
 128                 continue;
 129             for (MBeanAttributeInfo attr : attrs) {
 130                 if (attr.isReadable()) {
 131                     Object o = server.getAttribute(name, attr.getName());
 132                 }
 133             }
 134         }
 135         return names.size();
 136     }
 137 
 138 
 139     private static void testConnectLocal(int pid)
 140     throws Exception {
 141 
 142         String jmxUrlStr = null;
 143 
 144         try {
 145             jmxUrlStr = sun.management.ConnectorAddressLink.importFrom(pid);
 146             dbg_print("Local Service URL: " +jmxUrlStr);
 147             if ( jmxUrlStr == null ) {
 148                 throw new Exception("No Service URL. Local agent not started?");
 149             }
 150 
 151             JMXServiceURL url = new JMXServiceURL(jmxUrlStr);
 152             Map m = new HashMap();
 153 
 154             JMXConnector c = JMXConnectorFactory.connect(url,m);
 155 
 156             MBeanServerConnection conn = c.getMBeanServerConnection();
 157             ObjectName pattern = new ObjectName("java.lang:type=Memory,*");
 158 
 159             int count = listMBeans(conn,pattern,null);
 160             if (count == 0)
 161                 throw new Exception("Expected at least one matching "+
 162                                     "MBean for "+pattern);
 163 
 164         } catch (IOException e) {
 165             dbg_print("Cannot find process : " + pid);
 166             throw e;
 167         }
 168     }
 169 
 170     private static void testNoConnect(int port) throws Exception {
 171         testNoConnect(port, 0);
 172     }
 173 
 174     private static void testNoConnect(int port, int rmiPort) throws Exception {


 204         dbg_print("Using rmi port: " + rmiPort);
 205 
 206         Registry registry = LocateRegistry.getRegistry(port);
 207 
 208         // "jmxrmi"
 209         String[] relist = registry.list();
 210         for (int i = 0; i < relist.length; ++i) {
 211             dbg_print("Got registry: " + relist[i]);
 212         }
 213 
 214         String jmxUrlStr = (rmiPort != 0) ?
 215             String.format(
 216                 "service:jmx:rmi://localhost:%d/jndi/rmi://localhost:%d/jmxrmi",
 217                 rmiPort,
 218                 port) :
 219             String.format(
 220                 "service:jmx:rmi:///jndi/rmi://localhost:%d/jmxrmi",
 221                 port);
 222 
 223         JMXServiceURL url = new JMXServiceURL(jmxUrlStr);
 224         Map m = new HashMap();
 225 
 226         JMXConnector c = JMXConnectorFactory.connect(url,m);
 227 
 228         MBeanServerConnection conn = c.getMBeanServerConnection();
 229         ObjectName pattern = new ObjectName("java.lang:type=Memory,*");
 230 
 231         int count = listMBeans(conn,pattern,null);
 232         if (count == 0)
 233             throw new Exception("Expected at least one matching " +
 234                                 "MBean for " + pattern);
 235     }
 236 
 237     private static class Failure {
 238         private final Throwable cause;
 239         private final String msg;
 240 
 241         public Failure(Throwable cause, String msg) {
 242             this.cause = cause;
 243             this.msg = msg;
 244         }
 245 
 246         public Failure(String msg) {


 297         for (Method m : JMXStartStopTest.class.getDeclaredMethods()) {
 298             if (m.getName().startsWith("test_")) {
 299                 try {
 300                     m.invoke(null);
 301                     System.out.println("=== PASSED\n");
 302                 } catch (Throwable e) {
 303                     failures.add(new Failure(e, m.getName() + " failed"));
 304                 }
 305             }
 306         }
 307 
 308         if (!failures.isEmpty()) {
 309             for(Failure f : failures) {
 310                 System.err.println(f.getMsg());
 311                 f.getCause().printStackTrace(System.err);
 312             }
 313             throw new Error();
 314         }
 315     }
 316 
 317     /**
 318      * Retrieves the PID of the test application using JCMD
 319      * @return The PID of the test application
 320      * @throws InterruptedException
 321      * @throws IOException
 322      */
 323     private static String getPID() throws InterruptedException, IOException {
 324         final AtomicReference<String> pid = new AtomicReference<>();
 325         jcmd(
 326             null,
 327             line -> {
 328                 if (line.endsWith("JMXStartStopDoSomething")) {
 329                     pid.set(line.split(" ")[0]);
 330                 }
 331             }
 332         );
 333         return pid.get();
 334     }
 335 
 336     private static class Something {
 337         private Process p;
 338         private final ProcessBuilder pb;
 339         private final String name;
 340         private final AtomicBoolean started = new AtomicBoolean(false);
 341         private volatile int pid = -1;
 342 
 343         public Something(ProcessBuilder pb, String name) {
 344             this.pb = pb;
 345             this.name = name;
 346         }
 347 
 348         public synchronized void start() throws InterruptedException, IOException, TimeoutException {
 349             if (started.compareAndSet(false, true)) {
 350                 try {
 351                     p = ProcessTools.startProcess(
 352                         "JMXStartStopDoSomething",
 353                         pb,
 354                         (line) -> {
 355                             if (line.toLowerCase().startsWith("pid:")) {


 456 
 457         JDKToolLauncher l = JDKToolLauncher.createUsingTestJDK("jcmd");
 458         l.addToolArg(target);
 459         for(String cmd : command) {
 460             l.addToolArg(cmd);
 461         }
 462         Process p = ProcessTools.startProcess(
 463             "jcmd",
 464             new ProcessBuilder(l.getCommand()),
 465             c
 466         );
 467 
 468         p.waitFor();
 469         dbg_print("[jcmd] --------");
 470     }
 471 
 472     private static final String CMD_STOP = "ManagementAgent.stop";
 473     private static final String CMD_START= "ManagementAgent.start";
 474     private static final String CMD_START_LOCAL = "ManagementAgent.start_local";
 475 

 476     private static void test_01() throws Exception {
 477         // Run an app with JMX enabled stop it and
 478         // restart on other port
 479 
 480         System.out.println("**** Test one ****");
 481         PortAllocator pa = new PortAllocator();
 482 
 483         Something s = doSomething(
 484             "test_01",
 485             "-Dcom.sun.management.jmxremote.port=" + pa.getPort1(),
 486             "-Dcom.sun.management.jmxremote.authenticate=false",
 487             "-Dcom.sun.management.jmxremote.ssl=false");
 488 
 489         try {
 490             testConnect(pa.getPort1());
 491 
 492             jcmd(CMD_STOP);
 493             testNoConnect(pa.getPort1());
 494 
 495             jcmd(CMD_START, "jmxremote.port=" + pa.getPort2());
 496             testConnect(pa.getPort2());
 497         } finally {
 498             s.stop();
 499         }
 500     }
 501 

 502     private static void test_02() throws Exception {
 503         // Run an app without JMX enabled
 504         // start JMX by jcmd
 505 
 506         System.out.println("**** Test two ****");
 507 
 508         Something s = doSomething("test_02");
 509         PortAllocator pa = new PortAllocator();
 510         try {
 511             jcmd(CMD_START,
 512                 "jmxremote.port=" + pa.getPort1(),
 513                 "jmxremote.authenticate=false",
 514                 "jmxremote.ssl=false");
 515 
 516             testConnect(pa.getPort1());
 517         } finally {
 518 //            debugPortUsage(pa);
 519             s.stop();
 520         }
 521     }
 522 

 523     private static void test_03() throws Exception {
 524         // Run an app without JMX enabled
 525         // start JMX by jcmd on one port than on other one
 526 
 527         System.out.println("**** Test three ****");
 528 
 529         Something s = doSomething("test_03");
 530         PortAllocator pa = new PortAllocator();
 531         try {
 532             jcmd(CMD_START,
 533                 "jmxremote.port=" + pa.getPort1(),
 534                 "jmxremote.authenticate=false",
 535                 "jmxremote.ssl=false");
 536 
 537             // Second agent shouldn't start
 538             jcmd(CMD_START,
 539                 "jmxremote.port=" + pa.getPort2(),
 540                 "jmxremote.authenticate=false",
 541                 "jmxremote.ssl=false");
 542 
 543             // First agent should connect
 544             testConnect(pa.getPort1());
 545 
 546             // Second agent should not connect
 547             testNoConnect(pa.getPort2());
 548         } finally {
 549             s.stop();
 550         }
 551     }
 552 

 553     private static void test_04() throws Exception {
 554         // Run an app without JMX enabled
 555         // start JMX by jcmd on one port, specify rmi port explicitly
 556 
 557         System.out.println("**** Test four ****");
 558 
 559         Something s = doSomething("test_04");
 560         PortAllocator pa = new PortAllocator();
 561         try {
 562             jcmd(CMD_START,
 563                  "jmxremote.port=" + pa.getPort1(),
 564                  "jmxremote.rmi.port=" + pa.getPort2(),
 565                  "jmxremote.authenticate=false",
 566                  "jmxremote.ssl=false");
 567 
 568             testConnect(pa.getPort1(), pa.getPort2());
 569         } finally {
 570             s.stop();
 571         }
 572     }
 573 

 574     private static void test_05() throws Exception {
 575         // Run an app without JMX enabled, it will enable local server
 576         // but should leave remote server disabled
 577 
 578         System.out.println("**** Test five ****");
 579 
 580         Something s = doSomething("test_05");
 581         PortAllocator pa = new PortAllocator();
 582         try {
 583             jcmd(CMD_START_LOCAL);
 584 
 585             testNoConnect(pa.getPort1());
 586             testConnectLocal(s.getPid());
 587         } finally {
 588             s.stop();
 589         }
 590     }
 591 

 592     private static void test_06() throws Exception {
 593         // Run an app without JMX enabled
 594         // start JMX by jcmd on one port, specify rmi port explicitly
 595         // attempt to start it again
 596         // 1) with the same port
 597         // 2) with other port
 598         // 3) attempt to stop it twice
 599         // Check for valid messages in the output
 600 
 601         System.out.println("**** Test six ****");
 602 
 603         Something s = doSomething("test_06");
 604         PortAllocator pa = new PortAllocator();
 605         try {
 606             jcmd(CMD_START,
 607                  "jmxremote.port=" + pa.getPort1(),
 608                  "jmxremote.authenticate=false",
 609                  "jmxremote.ssl=false");
 610 
 611             testConnect(pa.getPort1(), pa.getPort2());


 619                 },
 620                 CMD_START,
 621                  "jmxremote.port=" + pa.getPort1(),
 622                  "jmxremote.authenticate=false",
 623                  "jmxremote.ssl=false");
 624 
 625             jcmd(
 626                 line -> {
 627                     if (line.contains("java.lang.RuntimeException: Invalid agent state")) {
 628                         checks[1] = true;
 629                     }
 630                 },
 631                 CMD_START,
 632                 "jmxremote.port=" + pa.getPort2(),
 633                 "jmxremote.authenticate=false",
 634                 "jmxremote.ssl=false");
 635 
 636             jcmd(CMD_STOP);
 637             jcmd(CMD_STOP);
 638 
 639             ServerSocket ss = new ServerSocket(0);
 640 
 641             jcmd(
 642                 line -> {
 643                     if (line.contains("Port already in use: " + ss.getLocalPort())) {
 644                         checks[2] = true;
 645                     }
 646                 },
 647                 CMD_START,
 648                 "jmxremote.port=" + ss.getLocalPort(),
 649                 "jmxremote.rmi.port=" + pa.getPort2(),
 650                 "jmxremote.authenticate=false",
 651                 "jmxremote.ssl=false");
 652 
 653             if (!checks[0]) {
 654                 throw new Exception("Starting agent on port " + pa.getPort1() + " should " +
 655                                     "report an invalid agent state");
 656             }
 657             if (!checks[1]) {
 658                 throw new Exception("Starting agent on poprt " + pa.getPort2() + " should " +
 659                                     "report an invalid agent state");
 660             }
 661             if (!checks[2]) {
 662                 throw new Exception("Starting agent on port " + ss.getLocalPort() + " should " +
 663                                     "report port in use");
 664             }

 665         } finally {
 666             s.stop();
 667         }
 668     }
 669 

 670     private static void test_07() throws Exception {
 671         // Run an app without JMX enabled, but with some properties set
 672         // in command line.
 673         // make sure these properties overridden corectly
 674 
 675         System.out.println("**** Test seven ****");
 676 
 677         Something s = doSomething(
 678             "test_07",
 679             "-Dcom.sun.management.jmxremote.authenticate=false",
 680             "-Dcom.sun.management.jmxremote.ssl=true");
 681         PortAllocator pa = new PortAllocator();
 682 
 683         try {
 684             testNoConnect(pa.getPort1());
 685             jcmd(
 686                 CMD_START,
 687                 "jmxremote.port=" + pa.getPort2(),
 688                 "jmxremote.authenticate=false",
 689                 "jmxremote.ssl=false"
 690             );
 691             testConnect(pa.getPort2());
 692         } finally {
 693             s.stop();
 694         }
 695     }
 696 

 697     private static void test_08() throws Exception {
 698         // Run an app with JMX enabled and with some properties set
 699         // in command line.
 700         // stop JMX agent and then start it again with different property values
 701         // make sure these properties overridden corectly
 702 
 703         System.out.println("**** Test eight ****");
 704         PortAllocator pa = new PortAllocator();
 705 
 706         Something s = doSomething(
 707             "test_08",
 708             "-Dcom.sun.management.jmxremote.port=" + pa.getPort1(),
 709             "-Dcom.sun.management.jmxremote.authenticate=false",
 710             "-Dcom.sun.management.jmxremote.ssl=true");
 711 
 712         try {
 713             testNoConnect(pa.getPort1());
 714 
 715             jcmd(CMD_STOP);
 716 
 717             testNoConnect(pa.getPort1());
 718 
 719             jcmd(
 720                 CMD_START,
 721                 "jmxremote.port=" + pa.getPort2(),
 722                 "jmxremote.authenticate=false",
 723                 "jmxremote.ssl=false"
 724             );
 725 
 726             testConnect(pa.getPort2());
 727         } finally {
 728             s.stop();
 729         }
 730     }
 731 

 732     private static void test_09() throws Exception {
 733         // Run an app with JMX enabled and with some properties set
 734         // in command line.
 735         // stop JMX agent and then start it again with different property values
 736         // specifing some property in management config file and some of them
 737         // in command line
 738         // make sure these properties overridden corectly
 739 
 740         System.out.println("**** Test nine ****");
 741 
 742         Something s = doSomething("test_09",
 743             "-Dcom.sun.management.config.file=" +
 744                 TEST_SRC + File.separator + "management_cl.properties",
 745             "-Dcom.sun.management.jmxremote.authenticate=false"
 746         );
 747         PortAllocator pa = new PortAllocator();
 748 
 749         try {
 750             testNoConnect(pa.getPort1());
 751 
 752             jcmd(CMD_STOP);
 753 
 754             testNoConnect(pa.getPort1());
 755 
 756             jcmd(CMD_START,
 757                 "config.file=" + TEST_SRC + File.separator +
 758                     "management_jcmd.properties",
 759                 "jmxremote.authenticate=false",
 760                 "jmxremote.port=" + pa.getPort2()
 761             );
 762 
 763             testConnect(pa.getPort2());
 764         } finally {
 765             s.stop();
 766         }
 767     }
 768 

 769     private static void test_10() throws Exception {
 770         // Run an app with JMX enabled and with some properties set
 771         // in command line.
 772         // stop JMX agent and then start it again with different property values
 773         // stop JMX agent again and then start it without property value
 774         // make sure these properties overridden corectly
 775 
 776         System.out.println("**** Test ten ****");
 777         PortAllocator pa = new PortAllocator();
 778 
 779         Something s = doSomething(
 780             "test_10",
 781             "-Dcom.sun.management.jmxremote.port=" + pa.getPort1(),
 782             "-Dcom.sun.management.jmxremote.authenticate=false",
 783             "-Dcom.sun.management.jmxremote.ssl=true");
 784 
 785         try {
 786             testNoConnect(pa.getPort1());
 787 
 788             jcmd(CMD_STOP);
 789             jcmd(CMD_START,
 790                 "jmxremote.ssl=false",
 791                 "jmxremote.port=" + pa.getPort1()
 792             );
 793             testConnect(pa.getPort1());
 794 
 795             jcmd(CMD_STOP);
 796             jcmd(CMD_START,
 797                 "jmxremote.port=" + pa.getPort1()
 798             );
 799 
 800             testNoConnect(pa.getPort1());
 801         } finally {
 802             s.stop();
 803         }
 804     }
 805 

 806     private static void test_11() throws Exception {
 807         // Run an app with JMX enabled
 808         // stop remote agent
 809         // make sure local agent is not affected
 810 
 811         System.out.println("**** Test eleven ****");
 812         PortAllocator pa = new PortAllocator();
 813 
 814         Something s = doSomething(
 815             "test_11",
 816             "-Dcom.sun.management.jmxremote.port=" + pa.getPort1(),
 817             "-Dcom.sun.management.jmxremote.authenticate=false",
 818             "-Dcom.sun.management.jmxremote.ssl=false");
 819         try {
 820             testConnect(pa.getPort1());
 821             jcmd(CMD_STOP);
 822             testConnectLocal(s.getPid());
 823         } finally {
 824             s.stop();
 825         }
 826     }
 827 

 828     private static void test_12() throws Exception {
 829         // Run an app with JMX disabled
 830         // start local agent only
 831 
 832         System.out.println("**** Test twelve ****");
 833 
 834         Something s = doSomething("test_12");
 835         PortAllocator pa = new PortAllocator();
 836 
 837         try {
 838             testNoConnect(pa.getPort1());
 839             jcmd(CMD_START + "_local");
 840 
 841             testConnectLocal(s.getPid());
 842 
 843         } finally {
 844             s.stop();
 845         }
 846     }
 847 
 848     private static void test_13() throws Exception {
 849         // Run an app with -javaagent make sure it works as expected -
 850         // system properties are ignored
 851 
 852         System.out.println("**** Test thirteen ****");
 853         PortAllocator pa = new PortAllocator();
 854 
 855         String agent = TEST_JDK + "/jre/lib/management-agent.jar";
 856         if (!new File(agent).exists()) {
 857             agent = TEST_JDK + "/lib/management-agent.jar";
 858         }
 859 
 860         Something s = doSomething("test_14",
 861             "-javaagent:" + agent + "=com.sun.management.jmxremote.port=" +
 862                 pa.getPort1() + ",com.sun.management.jmxremote.authenticate=false",
 863             "-Dcom.sun.management.jmxremote.ssl=false"
 864         );
 865 
 866         try {
 867             testNoConnect(pa.port1);
 868         } finally {
 869             s.stop();
 870         }
 871     }
 872 }

  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 import java.io.File;
  25 import java.io.IOException;
  26 import java.lang.reflect.Method;
  27 import java.net.ConnectException;
  28 import java.net.ServerSocket;
  29 import java.rmi.NoSuchObjectException;
  30 import java.rmi.registry.LocateRegistry;
  31 import java.rmi.registry.Registry;
  32 import java.util.ArrayList;
  33 import java.util.Arrays;

  34 import java.util.Iterator;
  35 import java.util.List;

  36 import java.util.Objects;
  37 import java.util.Set;
  38 import java.util.concurrent.TimeUnit;
  39 import java.util.concurrent.TimeoutException;
  40 import java.util.concurrent.atomic.AtomicBoolean;

  41 import java.util.function.Consumer;
  42 
  43 import javax.management.*;
  44 import javax.management.remote.*;
  45 import javax.net.ssl.SSLHandshakeException;
  46 
  47 import jdk.testlibrary.ProcessTools;
  48 import jdk.testlibrary.JDKToolLauncher;
  49 
  50 /**
  51  * @test
  52  * @bug 7110104
  53  * @library /lib/testlibrary
  54  * @build jdk.testlibrary.* JMXStartStopTest JMXStartStopDoSomething
  55  * @run main/othervm JMXStartStopTest
  56  * @summary Makes sure that enabling/disabling the management agent through
  57  *          JCMD achieves the desired results
  58  */
  59 public class JMXStartStopTest {

  60     private static final String TEST_SRC = System.getProperty("test.src");
  61 
  62     private static final boolean verbose = false;
  63 
  64     /**
  65      * Dynamically allocates two distinct ports using {@linkplain java.net.ServerSocket}
  66      * It keeps each of those ports blocked until it is first accessed by its getter
  67      */
  68     private static class PortAllocator {
  69         private final int port1, port2;
  70         private final ServerSocket ss1, ss2;
  71         PortAllocator() {
  72             try {
  73                 ss1 = new ServerSocket(0);
  74                 ss2 = new ServerSocket(0);
  75                 port1 = ss1.getLocalPort();
  76                 port2 = ss2.getLocalPort();
  77             } catch (IOException e) {
  78                 throw new Error("Error while obtaining free ports", e);
  79             }


  96                     ss2.close();
  97                 } catch (IOException e) {
  98                     // just ignore
  99                 }
 100             }
 101             return port2;
 102         }
 103     }
 104 
 105     private static void dbg_print(String msg){
 106         if (verbose) {
 107             System.out.println("DBG: " +msg);
 108         }
 109     }
 110 
 111     private static int listMBeans(MBeanServerConnection server,
 112                                   ObjectName pattern,
 113                                   QueryExp query)
 114     throws Exception {
 115 
 116         Set<ObjectName> names = server.queryNames(pattern,query);
 117         for (Iterator<ObjectName> i = names.iterator(); i.hasNext(); ) {
 118             ObjectName name = (ObjectName)i.next();
 119             MBeanInfo info = server.getMBeanInfo(name);
 120             dbg_print("Got MBean: " + name);
 121 
 122             MBeanAttributeInfo[] attrs = info.getAttributes();
 123             if (attrs == null)
 124                 continue;
 125             for (MBeanAttributeInfo attr : attrs) {
 126                 if (attr.isReadable()) {
 127                     server.getAttribute(name, attr.getName());
 128                 }
 129             }
 130         }
 131         return names.size();
 132     }
 133 
 134 
 135     private static void testConnectLocal(int pid)
 136     throws Exception {
 137 
 138         String jmxUrlStr = null;
 139 
 140         try {
 141             jmxUrlStr = sun.management.ConnectorAddressLink.importFrom(pid);
 142             dbg_print("Local Service URL: " +jmxUrlStr);
 143             if ( jmxUrlStr == null ) {
 144                 throw new Exception("No Service URL. Local agent not started?");
 145             }
 146 
 147             JMXServiceURL url = new JMXServiceURL(jmxUrlStr);

 148 
 149             JMXConnector c = JMXConnectorFactory.connect(url, null);
 150 
 151             MBeanServerConnection conn = c.getMBeanServerConnection();
 152             ObjectName pattern = new ObjectName("java.lang:type=Memory,*");
 153 
 154             int count = listMBeans(conn,pattern,null);
 155             if (count == 0)
 156                 throw new Exception("Expected at least one matching "+
 157                                     "MBean for "+pattern);
 158 
 159         } catch (IOException e) {
 160             dbg_print("Cannot find process : " + pid);
 161             throw e;
 162         }
 163     }
 164 
 165     private static void testNoConnect(int port) throws Exception {
 166         testNoConnect(port, 0);
 167     }
 168 
 169     private static void testNoConnect(int port, int rmiPort) throws Exception {


 199         dbg_print("Using rmi port: " + rmiPort);
 200 
 201         Registry registry = LocateRegistry.getRegistry(port);
 202 
 203         // "jmxrmi"
 204         String[] relist = registry.list();
 205         for (int i = 0; i < relist.length; ++i) {
 206             dbg_print("Got registry: " + relist[i]);
 207         }
 208 
 209         String jmxUrlStr = (rmiPort != 0) ?
 210             String.format(
 211                 "service:jmx:rmi://localhost:%d/jndi/rmi://localhost:%d/jmxrmi",
 212                 rmiPort,
 213                 port) :
 214             String.format(
 215                 "service:jmx:rmi:///jndi/rmi://localhost:%d/jmxrmi",
 216                 port);
 217 
 218         JMXServiceURL url = new JMXServiceURL(jmxUrlStr);

 219 
 220         JMXConnector c = JMXConnectorFactory.connect(url, null);
 221 
 222         MBeanServerConnection conn = c.getMBeanServerConnection();
 223         ObjectName pattern = new ObjectName("java.lang:type=Memory,*");
 224 
 225         int count = listMBeans(conn,pattern,null);
 226         if (count == 0)
 227             throw new Exception("Expected at least one matching " +
 228                                 "MBean for " + pattern);
 229     }
 230 
 231     private static class Failure {
 232         private final Throwable cause;
 233         private final String msg;
 234 
 235         public Failure(Throwable cause, String msg) {
 236             this.cause = cause;
 237             this.msg = msg;
 238         }
 239 
 240         public Failure(String msg) {


 291         for (Method m : JMXStartStopTest.class.getDeclaredMethods()) {
 292             if (m.getName().startsWith("test_")) {
 293                 try {
 294                     m.invoke(null);
 295                     System.out.println("=== PASSED\n");
 296                 } catch (Throwable e) {
 297                     failures.add(new Failure(e, m.getName() + " failed"));
 298                 }
 299             }
 300         }
 301 
 302         if (!failures.isEmpty()) {
 303             for(Failure f : failures) {
 304                 System.err.println(f.getMsg());
 305                 f.getCause().printStackTrace(System.err);
 306             }
 307             throw new Error();
 308         }
 309     }
 310 



















 311     private static class Something {
 312         private Process p;
 313         private final ProcessBuilder pb;
 314         private final String name;
 315         private final AtomicBoolean started = new AtomicBoolean(false);
 316         private volatile int pid = -1;
 317 
 318         public Something(ProcessBuilder pb, String name) {
 319             this.pb = pb;
 320             this.name = name;
 321         }
 322 
 323         public synchronized void start() throws InterruptedException, IOException, TimeoutException {
 324             if (started.compareAndSet(false, true)) {
 325                 try {
 326                     p = ProcessTools.startProcess(
 327                         "JMXStartStopDoSomething",
 328                         pb,
 329                         (line) -> {
 330                             if (line.toLowerCase().startsWith("pid:")) {


 431 
 432         JDKToolLauncher l = JDKToolLauncher.createUsingTestJDK("jcmd");
 433         l.addToolArg(target);
 434         for(String cmd : command) {
 435             l.addToolArg(cmd);
 436         }
 437         Process p = ProcessTools.startProcess(
 438             "jcmd",
 439             new ProcessBuilder(l.getCommand()),
 440             c
 441         );
 442 
 443         p.waitFor();
 444         dbg_print("[jcmd] --------");
 445     }
 446 
 447     private static final String CMD_STOP = "ManagementAgent.stop";
 448     private static final String CMD_START= "ManagementAgent.start";
 449     private static final String CMD_START_LOCAL = "ManagementAgent.start_local";
 450 
 451     @SuppressWarnings("unused")
 452     private static void test_01() throws Exception {
 453         // Run an app with JMX enabled stop it and
 454         // restart on other port
 455 
 456         System.out.println("**** Test one ****");
 457         PortAllocator pa = new PortAllocator();
 458 
 459         Something s = doSomething(
 460             "test_01",
 461             "-Dcom.sun.management.jmxremote.port=" + pa.getPort1(),
 462             "-Dcom.sun.management.jmxremote.authenticate=false",
 463             "-Dcom.sun.management.jmxremote.ssl=false");
 464 
 465         try {
 466             testConnect(pa.getPort1());
 467 
 468             jcmd(CMD_STOP);
 469             testNoConnect(pa.getPort1());
 470 
 471             jcmd(CMD_START, "jmxremote.port=" + pa.getPort2());
 472             testConnect(pa.getPort2());
 473         } finally {
 474             s.stop();
 475         }
 476     }
 477 
 478     @SuppressWarnings("unused")
 479     private static void test_02() throws Exception {
 480         // Run an app without JMX enabled
 481         // start JMX by jcmd
 482 
 483         System.out.println("**** Test two ****");
 484 
 485         Something s = doSomething("test_02");
 486         PortAllocator pa = new PortAllocator();
 487         try {
 488             jcmd(CMD_START,
 489                 "jmxremote.port=" + pa.getPort1(),
 490                 "jmxremote.authenticate=false",
 491                 "jmxremote.ssl=false");
 492 
 493             testConnect(pa.getPort1());
 494         } finally {
 495 //            debugPortUsage(pa);
 496             s.stop();
 497         }
 498     }
 499 
 500     @SuppressWarnings("unused")
 501     private static void test_03() throws Exception {
 502         // Run an app without JMX enabled
 503         // start JMX by jcmd on one port than on other one
 504 
 505         System.out.println("**** Test three ****");
 506 
 507         Something s = doSomething("test_03");
 508         PortAllocator pa = new PortAllocator();
 509         try {
 510             jcmd(CMD_START,
 511                 "jmxremote.port=" + pa.getPort1(),
 512                 "jmxremote.authenticate=false",
 513                 "jmxremote.ssl=false");
 514 
 515             // Second agent shouldn't start
 516             jcmd(CMD_START,
 517                 "jmxremote.port=" + pa.getPort2(),
 518                 "jmxremote.authenticate=false",
 519                 "jmxremote.ssl=false");
 520 
 521             // First agent should connect
 522             testConnect(pa.getPort1());
 523 
 524             // Second agent should not connect
 525             testNoConnect(pa.getPort2());
 526         } finally {
 527             s.stop();
 528         }
 529     }
 530 
 531     @SuppressWarnings("unused")
 532     private static void test_04() throws Exception {
 533         // Run an app without JMX enabled
 534         // start JMX by jcmd on one port, specify rmi port explicitly
 535 
 536         System.out.println("**** Test four ****");
 537 
 538         Something s = doSomething("test_04");
 539         PortAllocator pa = new PortAllocator();
 540         try {
 541             jcmd(CMD_START,
 542                  "jmxremote.port=" + pa.getPort1(),
 543                  "jmxremote.rmi.port=" + pa.getPort2(),
 544                  "jmxremote.authenticate=false",
 545                  "jmxremote.ssl=false");
 546 
 547             testConnect(pa.getPort1(), pa.getPort2());
 548         } finally {
 549             s.stop();
 550         }
 551     }
 552 
 553     @SuppressWarnings("unused")
 554     private static void test_05() throws Exception {
 555         // Run an app without JMX enabled, it will enable local server
 556         // but should leave remote server disabled
 557 
 558         System.out.println("**** Test five ****");
 559 
 560         Something s = doSomething("test_05");
 561         PortAllocator pa = new PortAllocator();
 562         try {
 563             jcmd(CMD_START_LOCAL);
 564 
 565             testNoConnect(pa.getPort1());
 566             testConnectLocal(s.getPid());
 567         } finally {
 568             s.stop();
 569         }
 570     }
 571 
 572     @SuppressWarnings("unused")
 573     private static void test_06() throws Exception {
 574         // Run an app without JMX enabled
 575         // start JMX by jcmd on one port, specify rmi port explicitly
 576         // attempt to start it again
 577         // 1) with the same port
 578         // 2) with other port
 579         // 3) attempt to stop it twice
 580         // Check for valid messages in the output
 581 
 582         System.out.println("**** Test six ****");
 583 
 584         Something s = doSomething("test_06");
 585         PortAllocator pa = new PortAllocator();
 586         try {
 587             jcmd(CMD_START,
 588                  "jmxremote.port=" + pa.getPort1(),
 589                  "jmxremote.authenticate=false",
 590                  "jmxremote.ssl=false");
 591 
 592             testConnect(pa.getPort1(), pa.getPort2());


 600                 },
 601                 CMD_START,
 602                  "jmxremote.port=" + pa.getPort1(),
 603                  "jmxremote.authenticate=false",
 604                  "jmxremote.ssl=false");
 605 
 606             jcmd(
 607                 line -> {
 608                     if (line.contains("java.lang.RuntimeException: Invalid agent state")) {
 609                         checks[1] = true;
 610                     }
 611                 },
 612                 CMD_START,
 613                 "jmxremote.port=" + pa.getPort2(),
 614                 "jmxremote.authenticate=false",
 615                 "jmxremote.ssl=false");
 616 
 617             jcmd(CMD_STOP);
 618             jcmd(CMD_STOP);
 619 
 620             try (ServerSocket ss = new ServerSocket(0))
 621             {
 622                 jcmd(
 623                     line -> {
 624                         if (line.contains("Port already in use: " + ss.getLocalPort())) {
 625                             checks[2] = true;
 626                         }
 627                     },
 628                     CMD_START,
 629                     "jmxremote.port=" + ss.getLocalPort(),
 630                     "jmxremote.rmi.port=" + pa.getPort2(),
 631                     "jmxremote.authenticate=false",
 632                     "jmxremote.ssl=false");
 633 
 634                 if (!checks[0]) {
 635                     throw new Exception("Starting agent on port " + pa.getPort1() + " should " +
 636                                         "report an invalid agent state");
 637                 }
 638                 if (!checks[1]) {
 639                     throw new Exception("Starting agent on poprt " + pa.getPort2() + " should " +
 640                                         "report an invalid agent state");
 641                 }
 642                 if (!checks[2]) {
 643                     throw new Exception("Starting agent on port " + ss.getLocalPort() + " should " +
 644                                         "report port in use");
 645                 }
 646             }
 647         } finally {
 648             s.stop();
 649         }
 650     }
 651 
 652     @SuppressWarnings("unused")
 653     private static void test_07() throws Exception {
 654         // Run an app without JMX enabled, but with some properties set
 655         // in command line.
 656         // make sure these properties overridden corectly
 657 
 658         System.out.println("**** Test seven ****");
 659 
 660         Something s = doSomething(
 661             "test_07",
 662             "-Dcom.sun.management.jmxremote.authenticate=false",
 663             "-Dcom.sun.management.jmxremote.ssl=true");
 664         PortAllocator pa = new PortAllocator();
 665 
 666         try {
 667             testNoConnect(pa.getPort1());
 668             jcmd(
 669                 CMD_START,
 670                 "jmxremote.port=" + pa.getPort2(),
 671                 "jmxremote.authenticate=false",
 672                 "jmxremote.ssl=false"
 673             );
 674             testConnect(pa.getPort2());
 675         } finally {
 676             s.stop();
 677         }
 678     }
 679 
 680     @SuppressWarnings("unused")
 681     private static void test_08() throws Exception {
 682         // Run an app with JMX enabled and with some properties set
 683         // in command line.
 684         // stop JMX agent and then start it again with different property values
 685         // make sure these properties overridden corectly
 686 
 687         System.out.println("**** Test eight ****");
 688         PortAllocator pa = new PortAllocator();
 689 
 690         Something s = doSomething(
 691             "test_08",
 692             "-Dcom.sun.management.jmxremote.port=" + pa.getPort1(),
 693             "-Dcom.sun.management.jmxremote.authenticate=false",
 694             "-Dcom.sun.management.jmxremote.ssl=true");
 695 
 696         try {
 697             testNoConnect(pa.getPort1());
 698 
 699             jcmd(CMD_STOP);
 700 
 701             testNoConnect(pa.getPort1());
 702 
 703             jcmd(
 704                 CMD_START,
 705                 "jmxremote.port=" + pa.getPort2(),
 706                 "jmxremote.authenticate=false",
 707                 "jmxremote.ssl=false"
 708             );
 709 
 710             testConnect(pa.getPort2());
 711         } finally {
 712             s.stop();
 713         }
 714     }
 715 
 716     @SuppressWarnings("unused")
 717     private static void test_09() throws Exception {
 718         // Run an app with JMX enabled and with some properties set
 719         // in command line.
 720         // stop JMX agent and then start it again with different property values
 721         // specifing some property in management config file and some of them
 722         // in command line
 723         // make sure these properties overridden corectly
 724 
 725         System.out.println("**** Test nine ****");
 726 
 727         Something s = doSomething("test_09",
 728             "-Dcom.sun.management.config.file=" +
 729                 TEST_SRC + File.separator + "management_cl.properties",
 730             "-Dcom.sun.management.jmxremote.authenticate=false"
 731         );
 732         PortAllocator pa = new PortAllocator();
 733 
 734         try {
 735             testNoConnect(pa.getPort1());
 736 
 737             jcmd(CMD_STOP);
 738 
 739             testNoConnect(pa.getPort1());
 740 
 741             jcmd(CMD_START,
 742                 "config.file=" + TEST_SRC + File.separator +
 743                     "management_jcmd.properties",
 744                 "jmxremote.authenticate=false",
 745                 "jmxremote.port=" + pa.getPort2()
 746             );
 747 
 748             testConnect(pa.getPort2());
 749         } finally {
 750             s.stop();
 751         }
 752     }
 753 
 754     @SuppressWarnings("unused")
 755     private static void test_10() throws Exception {
 756         // Run an app with JMX enabled and with some properties set
 757         // in command line.
 758         // stop JMX agent and then start it again with different property values
 759         // stop JMX agent again and then start it without property value
 760         // make sure these properties overridden corectly
 761 
 762         System.out.println("**** Test ten ****");
 763         PortAllocator pa = new PortAllocator();
 764 
 765         Something s = doSomething(
 766             "test_10",
 767             "-Dcom.sun.management.jmxremote.port=" + pa.getPort1(),
 768             "-Dcom.sun.management.jmxremote.authenticate=false",
 769             "-Dcom.sun.management.jmxremote.ssl=true");
 770 
 771         try {
 772             testNoConnect(pa.getPort1());
 773 
 774             jcmd(CMD_STOP);
 775             jcmd(CMD_START,
 776                 "jmxremote.ssl=false",
 777                 "jmxremote.port=" + pa.getPort1()
 778             );
 779             testConnect(pa.getPort1());
 780 
 781             jcmd(CMD_STOP);
 782             jcmd(CMD_START,
 783                 "jmxremote.port=" + pa.getPort1()
 784             );
 785 
 786             testNoConnect(pa.getPort1());
 787         } finally {
 788             s.stop();
 789         }
 790     }
 791 
 792     @SuppressWarnings("unused")
 793     private static void test_11() throws Exception {
 794         // Run an app with JMX enabled
 795         // stop remote agent
 796         // make sure local agent is not affected
 797 
 798         System.out.println("**** Test eleven ****");
 799         PortAllocator pa = new PortAllocator();
 800 
 801         Something s = doSomething(
 802             "test_11",
 803             "-Dcom.sun.management.jmxremote.port=" + pa.getPort1(),
 804             "-Dcom.sun.management.jmxremote.authenticate=false",
 805             "-Dcom.sun.management.jmxremote.ssl=false");
 806         try {
 807             testConnect(pa.getPort1());
 808             jcmd(CMD_STOP);
 809             testConnectLocal(s.getPid());
 810         } finally {
 811             s.stop();
 812         }
 813     }
 814 
 815     @SuppressWarnings("unused")
 816     private static void test_12() throws Exception {
 817         // Run an app with JMX disabled
 818         // start local agent only
 819 
 820         System.out.println("**** Test twelve ****");
 821 
 822         Something s = doSomething("test_12");
 823         PortAllocator pa = new PortAllocator();
 824 
 825         try {
 826             testNoConnect(pa.getPort1());
 827             jcmd(CMD_START + "_local");
 828 
 829             testConnectLocal(s.getPid());
 830 
 831         } finally {
 832             s.stop();
 833         }
 834     }
 835 
























 836 }