我有一些代码连接到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属性以在没有身份验证的情况下运行测试。我也想避免这样的事情,因为需要手动定义tools.jar并且想要使用常见的JMX工具。知道如何管理这个吗?
答案 0 :(得分:2)
身份验证配置在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的初始化方式。