Unable to start JMXConnectorServer

I would like to connect to my application via JMX remotely, so I created the following configuration in the main method:

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

      

This is how I start my application:

java -Dcom.sun.management.jmxremote 
     -Dcom.sun.management.jmxremote.port=7890
     -Dcom.sun.management.jmxremote.authenticate=false 
     -Dcom.sun.management.jmxremote.ssl=false 
     Main

      

But it seems like something is missing and I get the following exception:

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)

      

Could you please point me where I am going wrong?

+3


source to share


3 answers


The problem was that I didn't have an RMI registry, so just run this command in the console:

rmiregistry

      

or by adding this line of code before starting the server:



LocateRegistry.createRegistry(1099);

      

solves the problem.

+2


source


By running the app using java -Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port = 7890 -Dcom.sun.management.jmxremote.authenticate = false -Dcom.sun.management.jmxremote.ssl = false Home

you run a standard RMI JMX connector on port 7890. And you try to run a custom connector on the same port and it doesn't work.



If you are going to use your own connector instance, you can safely omit all -Dcom.sun.management.jmxremote properties . * .

+2


source


Below is a minimal working example for JDK 1.8, extended from https://docs.oracle.com/cd/E19698-01/816-7609/6mdjrf86t/index.html#security-ex-37 and https://docs.oracle .com / javase / 8 / docs / technotes / guides / jmx / tutorial / security.html # wp997065

The key missing steps from the code in the links and the accepted answers are:

  • LocateReigstry.createRegistry (port)
  • Thread.sleep () to make sure the application is not shutting down.
  • The answer does not describe MyAuthenticator. My answer is using a default authenticator that expects a path to access and password files.

Main.java working code:

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 content:

admin readwrite

      

Jmx.remote.x.password.file content:

admin password

      

I followed the code from maven using (assume 8474 is available):

javac Main.java
java Main  8474 jmxrmi   

      

0


source







All Articles