运行时为 JMX 设置 JVM 参数



我有一些代码连接到JMX并按名称获取mBean。现在我正在用JUnit为它编写测试。我已经使用如下内容在没有身份验证的情况下进行了一些测试:

private static void startJmxServer() throws Exception {
  MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
  LocateRegistry.createRegistry(PORT);
  JMXServiceURL url = new JMXServiceURL("service:jmx:rmi:///jndi/rmi://" + HOST + ':' + PORT + "/jmxrmi");
  JMXConnectorServer connectorServer = JMXConnectorServerFactory.newJMXConnectorServer(url, null, mbs);
  Example exampleMBean = new Example();
  ObjectName exampleName = new ObjectName(MBEAN_NAME);
  mbs.registerMBean(exampleMBean, exampleName);
  connectorServer.start();
} 

现在我想用身份验证做一些测试。所以我需要指定下一个 JVM 项目:

-Dcom.sun.management.jmxremote
-Dcom.sun.management.jmxremote.port=1234
-Dcom.sun.management.jmxremote.authenticate=true
-Dcom.sun.management.jmxremote.ssl=false
-Dcom.sun.management.jmxremote.access.file=/somepath/jmxremote.access
-Dcom.sun.management.jmxremote.password.file=/somepath/jmxremote.password

我已经尝试JMXConnectorServer环境变量中传递此属性。我也试过System.setProperty.但是失败了,因为连接在没有任何凭据的情况下可用。使其工作的唯一方法是:

private static void startJmxServer() throws Exception {
    String name = ManagementFactory.getRuntimeMXBean().getName();
    VirtualMachine vm = VirtualMachine.attach(name.substring(0, name.indexOf('@')));
    String lca = vm.getAgentProperties().getProperty("com.sun.management.jmxremote.localConnectorAddress");
    if (lca == null) {
        Path p = Paths.get(System.getProperty("java.home")).normalize();
        if (!"jre".equals(p.getName(p.getNameCount() - 1).toString()
            .toLowerCase())) {
            p = p.resolve("jre");
        }
        File f = p.resolve("lib").resolve("management-agent.jar").toFile();
        if (!f.exists()) {
            throw new IOException("Management agent not found");
        }
        String options = String.format("com.sun.management.jmxremote.port=%d, " +
            "com.sun.management.jmxremote.authenticate=true, " +
            "com.sun.management.jmxremote.ssl=false, " +
            "com.sun.management.jmxremote.access.file=/somepath/jmxremote.access, " +
            "com.sun.management.jmxremote.password.file=/somepath/jmxremote.password", PORT);
        vm.loadAgent(f.getCanonicalPath(), options);
    }
    vm.detach();
    MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
    Example exampleMBean = new Example();
    ObjectName exampleName = new ObjectName(MBEAN_NAME);
    mbs.registerMBean(exampleMBean, exampleName);
}

但是由于加载了代理,我无法更改 VM 属性以在没有身份验证的情况下运行测试。我也想避免这种事情,因为需要手动定义工具.jar并希望使用常见的JMX工具。知道如何管理吗?

身份验证配置在environment中传递 - 第二个参数JMXConnectorServerFactory.newJMXConnectorServer

    HashMap<String, Object> env = new HashMap<>();
    env.put("jmx.remote.x.password.file", "/somepath/jmxremote.password");
    env.put("jmx.remote.x.access.file", "/somepath/jmxremote.access");
    JMXConnectorServer connectorServer =
        JMXConnectorServerFactory.newJMXConnectorServer(url, env, mbs);

请注意,此处的属性名称与属性名称不同。

请查阅 JDK 源中的 ConnectorBootstrap.java,了解如何初始化默认的 JMXConnectorServer。

最新更新