Although it's the easiest way to open a JMX connection, RMI protocol requires to edit security groups to open a ports.
It's good for dev only environment. In case JMX is necessary for your Prod env, JMXMP is a more secured solution, but it requires more setup. Refer to section "Jmxmp protocol" for more details.
In order to enable JMX remote access, all to do is adding Java system properties.
If you just want copy and paste to make it works, jump to the following for sample docker file.
First, to make it simple, we start with unsecured configs.
Heads-up ! Everybody who knows your hostname can scan the port and connect to your application to monitor or even calls the methods of your Jmx bean. So, never do this on your prod env.
For Java application running at localhost, JMX is already availble. Just start JVisualVM and connect to your app.
If your app is running inside a docker and it does not even run at local, you need to enable JMX remote connection.
Simply add the following system property when application starts
JAVA_OPTS="-Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port=<jmx_port> -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false -Djava.net.preferIPv4Stack=true -Djava.rmi.server.hostname=<rmi_host> -Dcom.sun.management.jmxremote.rmi.port=<rmi_port> -Dcom.sun.management.jmxremote.local.only=false java $JAVA_OPTS -jar app.jar
Start JVisualVm, choose menu File > Add JMX connection, then input in Connection
<docker_ip> is the IP address of your docker container.
If you run your docker container with network=host, <docker_ip>=localhost
If the docker conatiner run with bridge network, run docker inspect
docker inspect <containerid>
In the json response, check the field Network>Bridge>IPAddress
<jmx_port> is the port number in system property "com.sun.management.jmxremote.port" (above)
As the destination is not localhost, we set local.only=false
For simplicity, we disable the authentications and ssl connection.
There are still 2 system parameters:
First, JVisualVM connect to <docker_ip>:<jmx_port> to receive from the Java app the <rmi_host>:<rmi_port> and then JVisualVM starts to connect to it to get the data.
It's fine to have <rmi_port> to be the same as <jmx_port>. However, it's important that JVisualVM can reach that rmi_host:rmi_port.
That implies that the rmi_host must be a public IP, not a private IP and the docker exposes the port rmi_port.
The parameter preferIpV4Stack is not necessary for docker running at local host. It's only needed for ECS AWS.
Sample dockerfile can be found here
Now if your docker is running on a EC2 instance, it's important to ensure that
1) <rmi_host> is the public IP of your EC2. From you local machine, you should be able to run telnet <rmi_host>:<rmi_port> and <rmi_host>:<jmx_port>
2) docker export 2 ports <rmi_port> and <jmx_port>
3) Add inbound rules for <rmi_port>, <jmx_port> on your EC2 instance:
Open EC2 > Network & Security > Security Groups
Action > Edit Inbound Rules
Add rules for <jmx_port> and <rmi_port>