简体   繁体   English

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

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

I am trying to implement a monitoring control based on an RMI connector for JMX, for an application launcher via WebStart. 我正在尝试通过WebStart为应用程序启动器基于JMX的RMI连接器实现监视控件。

The connectors work fine no matter how I start them when the application is started from the command-line or IDE. 无论我从命令行或IDE启动应用程序时如何启动它们,连接器都可以正常工作。 However, everything goes south when I try to inspect it when it's been launched by invoking the JNLP file with javaws. 但是,当我尝试通过使用javaws调用JNLP文件启动它检查时,一切都变了。

I have tried several approaches: 我尝试了几种方法:

  • using the built-in JMX features, by specifying the following variables in JAVAWS_VM_ARGS (docs say it should work in 1.6, but people report it doesn't; they don't appear to be set at all in the resulting process, if I inspect it using the Attach API): 使用内置的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 
  • using the built-in JMX features, by specifying the following variables in the JNLP file (some say this shouldn't work, and indeed they don't seem to be set when I inspect with the Attach API; the JNLP is set with all-permissions as well): 使用内置的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" /> 
  • using the built-in JMX features, by specifying the following variables using -J options to the calling javaws program (they don't appear to be set at all in the resulting process, if I inspect it using the Attach API): 使用内置的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 
  • using a custom JMXConnectorServer with the following code (connection is still refused as with the previous attempts, with "Connection Failed. Retry? The connection did not succeed."): 使用具有以下代码的自定义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(); } 

I try to connect with JConsole (ultimately, this will be done from another program, but I try from JConsole to verify the JMX service is running correctly) with this JMXServiceURL: 我尝试使用以下JMXServiceURL与JConsole连接(最终,这将通过另一个程序来完成,但是我尝试从JConsole验证JMX服务是否正常运行):

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

Does anyone have any idea how to do this, either programmatically or how to get these properties passed to the WebStart-ed process? 有谁知道如何以编程方式执行此操作,或者如何将这些属性传递给WebStart-ed流程?

Thanks in advance. 提前致谢。

Additional Notes 补充笔记

  • this is for Java 1.6+ (not 1.5). 这是针对Java 1.6+(而非1.5)的。
  • these options do work when I invoke my program directly and pass them via the command-line. 这些选项工作时,我直接调用我的程序,并通过命令行传递它们。
  • Some mentioned specifying the IP directly, using java.rmi.server.hostname=YOUR_IP. 有人提到使用java.rmi.server.hostname = YOUR_IP直接指定IP。 However, this doesn't seem require when the process is started normally, so I don't think it would be relevant to the WebStart scenario. 但是,正常启动该过程时似乎并不需要,因此我认为这与WebStart场景无关。
  • I can use a connection with the Attach API to connect to a process by PID with JConsole or JVisualVM, but ultimately the product cannot rely on this, as it requires a JDK or to bundle the tools.jar, and I don't think there are open alternatives to this. 我可以使用带有Attach API的连接来通过JConsole或JVisualVM通过PID连接到进程,但是最终产品不能依赖于此,因为它需要JDK或将tools.jar捆绑在一起,我不认为在那里是对此的开放替代方案。 If there is, that would actually be a lot easier so let me know if you know one. 如果有,那实际上会容易得多,所以如果您知道一个,请告诉我。

Update: 更新:

Actually, when using my last example with an explicit JMXConnectorServer , I get an NPE at the launch-time of the WebStart process, with: 实际上,当将我的最后一个示例与显式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

As discussed with jtahlborn in the question's comment, we worked out that this was really specific to the application's setup. 正如在问题注释中与jtahlborn讨论的那样,我们发现这确实是针对应用程序设置的。

There are some pitfalls to address to make JMX work for WebStart-ed applications, and there's also some implications to the use of multiple JNDI context factories. 使JMX在WebStart-ed应用程序中工作需要解决一些陷阱,并且对使用多个JNDI上下文工厂也有一些影响。

In this particular case, the application had a jndi.properties read on startup and populating configuration settings, so a JBoss JNDI context factory was already even at the call point of the static block of the WebStart-ed application's entry-point / main-class. 在这种特殊情况下,应用程序在启动和填充配置设置时读取了jndi.properties ,因此,JBoss JNDI上下文工厂已经位于WebStart-ed应用程序的入口点/主类的静态块的调用点处。 。

As these JNDI properties were necessary for the rest of the program, the solution is simply to override these properties when creating the JMXServerConnector programmatically. 由于这些JNDI属性对于程序的其余部分是必需的,因此解决方案就是在以编程方式创建JMXServerConnector时简单地覆盖这些属性。

Here's an example: 这是一个例子:

    @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));
        }});
    }

and: 和:

    // 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();
    }

Note: I assume you could probably do it the other way around and override these properties on the command-line or in the JNLP file, and then reset them to whatever is needed for later contexts. 注意:我想您可能会采取其他方法,并在命令行或JNLP文件中覆盖这些属性,然后将它们重置为以后上下文所需的内容。 However, this didn't fit the use case here so I didn't really look into it. 但是,这不适合这里的用例,因此我没有真正研究它。

try setting following argument from command line on windows 尝试在Windows上的命令行中设置以下参数

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

and then start the jnlp file from that same command prompt. 然后从同一命令提示符启动jnlp文件。 It worked for me. 它为我工作。

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

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