繁体   English   中英

如何在WebStart流程中使用JMX RMI代理?

[英]How to use a JMX RMI agent in a WebStart process?

我正在尝试通过WebStart为应用程序启动器基于JMX的RMI连接器实现监视控件。

无论我从命令行或IDE启动应用程序时如何启动它们,连接器都可以正常工作。 但是,当我尝试通过使用javaws调用JNLP文件启动它检查时,一切都变了。

我尝试了几种方法:

  • 使用内置的JMX功能,通过在JAVAWS_VM_ARGS中指定以下变量(文档说它应该在1.6中起作用,但是人们报告说它不起作用;如果我检查了结果过程中,它们似乎根本没有设置)使用附加API):

     -Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.local.only=true -Dcom.sun.management.jmxremote.port=SOME_PORT_HERE -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false 
  • 使用内置的JMX功能,通过在JNLP文件中指定以下变量(有人说这不起作用,实际上在我使用Attach API进行检查时似乎没有设置它们; JNLP设置了所有-权限):

     <property name="com.sun.management.jmxremote.local.only" value="true" /> <property name="com.sun.management.jmxremote.port" value="SOME_PORT_HERE" /> <property name="com.sun.management.jmxremote.authenticate" value="false" /> <property name="com.sun.management.jmxremote.ssl" value="false" /> 
  • 使用内置的JMX功能,通过在调用javaws程序中使用-J选项指定以下变量(如果我使用Attach API检查它们,它们在结果过程中似乎根本没有设置):

     -J-Dcom.sun.management.jmxremote -J-Dcom.sun.management.jmxremote.local.only=true -J-Dcom.sun.management.jmxremote.port=SOME_PORT_HERE -J-Dcom.sun.management.jmxremote.authenticate=false -J-Dcom.sun.management.jmxremote.ssl=false 
  • 使用具有以下代码的自定义JMXConnectorServer(仍然像以前的尝试一样拒绝连接,并显示“连接失败。重试?连接未成功。”):

      try { final MBeanServer mbs = ManagementFactory.getPlatformMBeanServer(); final String jmxPort = System.getProperty("jmx.port"); if (jmxPort != null) { final int port = Integer.parseInt(jmxPort); System.out.println("settings JMX properties"); System.setProperty("java.rmi.server.randomIDs", "true"); Map<String, String> env = new HashMap<String, String>(); env.put("com.sun.management.jmxremote.ssl", "false"); env.put("com.sun.management.jmxremote.authenticate", "false"); env.put("com.sun.management.jmxremote.local.only", "true"); System.out.println("Creating Locate Registry"); LocateRegistry.createRegistry(port); System.out.println("Creating JMX Service URL"); JMXServiceURL url = new JMXServiceURL("service:jmx:rmi:///jndi/rmi://localhost:" + port + "/server"); System.out.println("Creating new JMX Connector Server"); JMXConnectorServer cs = JMXConnectorServerFactory.newJMXConnectorServer(url, env, mbs); cs.start(); } } catch (final RemoteException e) { e.printStackTrace(); } catch (final MalformedURLException e) { e.printStackTrace(); } catch (final IOException e) { e.printStackTrace(); } 

我尝试使用以下JMXServiceURL与JConsole连接(最终,这将通过另一个程序来完成,但是我尝试从JConsole验证JMX服务是否正常运行):

    service:jmx:rmi:///jndi/rmi://localhost:SOME_PORT_HERE/jmxrmi

有谁知道如何以编程方式执行此操作,或者如何将这些属性传递给WebStart-ed流程?

提前致谢。

补充笔记

  • 这是针对Java 1.6+(而非1.5)的。
  • 这些选项工作时,我直接调用我的程序,并通过命令行传递它们。
  • 有人提到使用java.rmi.server.hostname = YOUR_IP直接指定IP。 但是,正常启动该过程时似乎并不需要,因此我认为这与WebStart场景无关。
  • 我可以使用带有Attach API的连接来通过JConsole或JVisualVM通过PID连接到进程,但是最终产品不能依赖于此,因为它需要JDK或将tools.jar捆绑在一起,我不认为在那里是对此的开放替代方案。 如果有,那实际上会容易得多,所以如果您知道一个,请告诉我。

更新:

实际上,当将我的最后一个示例与显式JMXConnectorServer ,我在WebStart进程启动时获得了NPE,其内容如下:

12:39:28,743 WARN  [App] [trce] java.lang.NullPointerException
 at org.jboss.security.jndi.LoginInitialContextFactory.getInitialContext(LoginInitialContextFactory.java:81)
 at javax.naming.spi.NamingManager.getInitialContext(NamingManager.java:667)
 at javax.naming.InitialContext.getDefaultInitCtx(InitialContext.java:288)
 at javax.naming.InitialContext.init(InitialContext.java:223)
 at javax.naming.InitialContext.<init>(InitialContext.java:197)
 at javax.management.remote.rmi.RMIConnectorServer.bind(RMIConnectorServer.java:619)
 at javax.management.remote.rmi.RMIConnectorServer.start(RMIConnectorServer.java:412)
 // line invoking .start() on the JMXConnectorServer's instance

正如在问题注释中与jtahlborn讨论的那样,我们发现这确实是针对应用程序设置的。

使JMX在WebStart-ed应用程序中工作需要解决一些陷阱,并且对使用多个JNDI上下文工厂也有一些影响。

在这种特殊情况下,应用程序在启动和填充配置设置时读取了jndi.properties ,因此,JBoss JNDI上下文工厂已经位于WebStart-ed应用程序的入口点/主类的静态块的调用点处。 。

由于这些JNDI属性对于程序的其余部分是必需的,因此解决方案就是在以编程方式创建JMXServerConnector时简单地覆盖这些属性。

这是一个例子:

    @SuppressWarnings("serial")
    private static Properties   initProperties() {
        return (new Properties() {{
            // overrides for the JNDI factory
            // mostly changing the INITIAL_CONTEXT_FACTORY from:
            //   "org.jboss.security.jndi.JndiLoginInitialContextFactory"
            // to:
            put(Context.INITIAL_CONTEXT_FACTORY,
                "org.jnp.interfaces.NamingContextFactory");
            put(Context.PROVIDER_URL, "jnp://localhost/");

            // Required JMX properties and other things ...
            //  YMMV of course, these were for my current settings
            put("java.rmi.server.randomIDs", "true");
            put("java.rmi.server.hostname", host); // host needs to be an IP
            put("com.sun.management.jmxremote.ssl", "false");
            put("com.sun.management.jmxremote.authenticate", "false");
            put("com.sun.management.jmxremote.local.only", "true");
            put("com.sun.management.jmxremote.port", String.valueOf(port));
        }});
    }

和:

    // error handling left out for clarity
    private static void startJMXAgent() throws TheWorld {
        Registry           reg  = LocateRegistry.createRegistry(port);
        JMXConnectorServer cs   =
            JMXConnectorServerFactory.newJMXConnectorServer(
                new JMXServiceURL(
                    "service:jmx:rmi://" + host + ":" + port + "/" +
                    "jndi/rmi://" + host + ":" + port + "/" +
                    servicename
                ),
                initProperties(),
                ManagementFactory.getPlatformMBeanServer()
            );
        cs.start();
    }

注意:我想您可能会采取其他方法,并在命令行或JNLP文件中覆盖这些属性,然后将它们重置为以后上下文所需的内容。 但是,这不适合这里的用例,因此我没有真正研究它。

尝试在Windows上的命令行中设置以下参数

设置JAVAWS_VM_ARGS = -Dcom.sun.management.jmxremote.port = 9400 -Dcom.sun.management.jmxremote.authenticate = false -Dcom.sun.management.jmxremote.ssl = false

然后从同一命令提示符启动jnlp文件。 它为我工作。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM