我想通过JMX远程连接到我的应用程序,所以我在main方法中创建了以下配置:
MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
JMXServiceURL url = new JMXServiceURL("service:jmx:rmi:///jndi/rmi://localhost:7890/jmxrmi");
Map<String, Object> envConf = new HashMap<>();
//My custom authenticator
envConf.put(JMXConnectorServer.AUTHENTICATOR, new MyAuthenticator(jmxUsername, jmxPassword));
JMXConnectorServer cs = JMXConnectorServerFactory.newJMXConnectorServer(url, envConf, mbs);
cs.start();
以下是我启动应用程序的方法:
java -Dcom.sun.management.jmxremote
-Dcom.sun.management.jmxremote.port=7890
-Dcom.sun.management.jmxremote.authenticate=false
-Dcom.sun.management.jmxremote.ssl=false
Main
但似乎缺少某些东西,我得到了以下异常:
Cannot bind to URL [rmi://localhost:7890/jmxrmi]: javax.naming.NoPermissionException [Root exception is java.rmi.ServerException: RemoteException occurred in server thread; nested exception is:
java.rmi.AccessException: Cannot modify this registry]
java.io.IOException: Cannot bind to URL [rmi://localhost:7890/jmxrmi]: javax.naming.NoPermissionException [Root exception is java.rmi.ServerException: RemoteException occurred in server thread; nested exception is:
java.rmi.AccessException: Cannot modify this registry]
at javax.management.remote.rmi.RMIConnectorServer.newIOException(RMIConnectorServer.java:827)
at javax.management.remote.rmi.RMIConnectorServer.start(RMIConnectorServer.java:432)
at test.jms.Main.start(JmxModule.java:35)
Caused by: javax.naming.NoPermissionException [Root exception is java.rmi.ServerException: RemoteException occurred in server thread; nested exception is:
java.rmi.AccessException: Cannot modify this registry]
at com.sun.jndi.rmi.registry.RegistryContext.bind(RegistryContext.java:147)
at com.sun.jndi.toolkit.url.GenericURLContext.bind(GenericURLContext.java:228)
at javax.naming.InitialContext.bind(InitialContext.java:425)
at javax.management.remote.rmi.RMIConnectorServer.bind(RMIConnectorServer.java:644)
at javax.management.remote.rmi.RMIConnectorServer.start(RMIConnectorServer.java:427)
... 4 more
Caused by: java.rmi.ServerException: RemoteException occurred in server thread; nested exception is:
java.rmi.AccessException: Cannot modify this registry
at sun.rmi.server.UnicastServerRef.oldDispatch(UnicastServerRef.java:420)
at sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:268)
at sun.rmi.transport.Transport$1.run(Transport.java:200)
at sun.rmi.transport.Transport$1.run(Transport.java:197)
at java.security.AccessController.doPrivileged(Native Method)
at sun.rmi.transport.Transport.serviceCall(Transport.java:196)
at sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:568)
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:826)
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.lambda$run$254(TCPTransport.java:683)
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler$$Lambda$13/8098086.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:682)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
at sun.rmi.transport.StreamRemoteCall.exceptionReceivedFromServer(StreamRemoteCall.java:276)
at sun.rmi.transport.StreamRemoteCall.executeCall(StreamRemoteCall.java:253)
at sun.rmi.server.UnicastRef.invoke(UnicastRef.java:379)
at sun.rmi.registry.RegistryImpl_Stub.bind(Unknown Source)
at com.sun.jndi.rmi.registry.RegistryContext.bind(RegistryContext.java:141)
... 8 more
Caused by: java.rmi.AccessException: Cannot modify this registry
at sun.management.jmxremote.SingleEntryRegistry.bind(SingleEntryRegistry.java:76)
at sun.rmi.registry.RegistryImpl_Skel.dispatch(Unknown Source)
at sun.rmi.server.UnicastServerRef.oldDispatch(UnicastServerRef.java:410)
at sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:268)
at sun.rmi.transport.Transport$1.run(Transport.java:200)
at sun.rmi.transport.Transport$1.run(Transport.java:197)
at java.security.AccessController.doPrivileged(Native Method)
at sun.rmi.transport.Transport.serviceCall(Transport.java:196)
at sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:568)
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:826)
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.lambda$run$254(TCPTransport.java:683)
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler$$Lambda$13/8098086.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:682)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
请指点我错在哪里?
答案 0 :(得分:3)
通过启动应用程序使用 java -Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port = 7890 -Dcom.sun.management.jmxremote.authenticate = FALSE -Dcom.sun.management.jmxremote.ssl = FALSE 主
您正在端口7890上启动默认的RMI JMX连接器。并且您正尝试在同一端口上启动自定义连接器,但它失败。
如果您要使用自己的连接器实例,可以安全地省略所有 -Dcom.sun.management.jmxremote。* 属性。
答案 1 :(得分:2)
问题是我没有运行RMI注册表,所以只需在控制台中运行此命令:
rmiregistry
或在启动服务器之前添加以下代码行:
LocateRegistry.createRegistry(1099);
解决了一个问题。
答案 2 :(得分:0)
以下是从https://docs.oracle.com/cd/E19698-01/816-7609/6mdjrf86t/index.html#security-ex-37和https://docs.oracle.com/javase/8/docs/technotes/guides/jmx/tutorial/security.html#wp997065扩展的JDK 1.8的最小工作示例
链接中代码中缺少的关键步骤和接受的答案是:
工作代码Main.java:
import javax.management.MBeanServer;
import javax.management.remote.JMXConnectorServer;
import javax.management.remote.JMXConnectorServerFactory;
import javax.management.remote.JMXServiceURL;
import java.lang.management.ManagementFactory;
import java.rmi.registry.LocateRegistry;
import java.util.*;
public class Main {
public static void main(String[] args) throws Exception {
if(args.length != 2) {
throw new IllegalArgumentException("Main <port> <path suffix>"
+ "\nservice:jmx:rmi:///jndi/rmi://localhost:<port>/<pathsuffix>"
);
}
int port = Integer.parseInt(args[0]);
String pathSuffix = args[1];
LocateRegistry.createRegistry(port);
MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
JMXServiceURL url = new JMXServiceURL("service:jmx:rmi:///jndi/rmi://0.0.0.0:" + port + "/" + pathSuffix);
Map<String, Object> envConf = new HashMap<>();
envConf.put("jmx.remote.x.password.file", "password.properties");
envConf.put("jmx.remote.x.access.file", "access.properties");
JMXConnectorServer cs = JMXConnectorServerFactory.newJMXConnectorServer(url, envConf, mbs);
cs.start();
while(true) {
Thread.sleep(1000);
}
}
}
jmx.remote.x.access.file的内容:
admin readwrite
jmx.remote.x.password.file的内容:
admin password
我使用maven执行代码(假设8474可用):
javac Main.java
java Main 8474 jmxrmi