Has anyone ever got a remote JMX JConsole to work?
Solution 1:
I have a solution for this:
If your Java process is running on Linux behind a firewall and you want to start JConsole / Java VisualVM / Java Mission Control on Windows on your local machine to connect it to the JMX Port of your Java process.
You need access to your linux machine via SSH login. All Communication will be tunneled over the SSH connection.
TIP: This Solution works no matter if there is a firewall or not.
Disadvantage: Everytime you restart your java process, you will need to do all steps from 4 - 9 again.
1. You need the putty-suite for your Windows machine from here:
http://www.chiark.greenend.org.uk/~sgtatham/putty/download.html
At least the putty.exe
2. Define one free Port on your linux machine:
<jmx-remote-port>
Example:
jmx-remote-port = 15666
3. Add arguments to java process on the linux machine
This must be done exactly like this. If its done like below, it works for linux Machines behind firewalls (It works cause of the -Djava.rmi.server.hostname=localhost
argument).
-Dcom.sun.management.jmxremote
-Dcom.sun.management.jmxremote.port=<jmx-remote-port>
-Dcom.sun.management.jmxremote.ssl=false
-Dcom.sun.management.jmxremote.authenticate=false
-Dcom.sun.management.jmxremote.local.only=false
-Djava.rmi.server.hostname=localhost
Example:
java -Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port=15666 -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.local.only=false -Djava.rmi.server.hostname=localhost ch.sushicutta.jmxremote.Main
4. Get Process-Id of your Java Process
ps -ef | grep <java-processname>
result ---> <process-id>
Example:
ps -ef | grep ch.sushicutta.jmxremote.Main
result ---> 24321
5. Find arbitrary Port for RMIServer stubs download
The java process opens a new TCP Port on the linux machine, where the RMI Server-Stubs will be available for download. This port also needs to be available via SSH Tunnel to get a connection to the Java Virtual Machine.
With netstat -lp
this port can be found also the lsof -i
gives hints what port has been opened form the java process.
NOTE: This port always changes when java process is started.
netstat -lp | grep <process-id>
tcp 0 0 *:<jmx-remote-port> *:* LISTEN 24321/java
tcp 0 0 *:<rmi-server-port> *:* LISTEN 24321/java
result ---> <rmi-server-port>
Example:
netstat -lp | grep 24321
tcp 0 0 *:15666 *:* LISTEN 24321/java
tcp 0 0 *:37123 *:* LISTEN 24321/java
result ---> 37123
6. Enable two SSH-Tunnels from your Windows machine with putty
Source port: <jmx-remote-port>
Destination: localhost:<jmx-remote-port>
[x] Local
[x] Auto
Source port: <rmi-server-port>
Destination: localhost:<rmi-server-port>
[x] Local
[x] Auto
Example:
Source port: 15666
Destination: localhost:15666
[x] Local
[x] Auto
Source port: 37123
Destination: localhost:37123
[x] Local
[x] Auto
7. Login to your Linux machine with Putty with this SSH-Tunnel enabled.
Leave the putty session open.
When you are logged in, Putty will tunnel all TCP-Connections to the linux machine over the SSH port 22.
JMX-Port:
Windows machine: localhost:15666 >>> SSH >>> linux machine: localhost:15666
RMIServer-Stub-Port:
Windows Machine: localhost:37123 >>> SSH >>> linux machine: localhost:37123
8. Start JConsole / Java VisualVM / Java Mission Control to connect to your Java Process using the following URL
This works, cause JConsole / Java VisualVM / Java Mission Control thinks you connect to a Port on your local Windows machine. but Putty send all payload to the port 15666 to your linux machine.
On the linux machine first the java process gives answer and send back the RMIServer Port. In this example 37123.
Then JConsole / Java VisualVM / Java Mission Control thinks it connects to localhost:37123 and putty will send the whole payload forward to the linux machine
The java Process answers and the connection is open.
[x] Remote Process:
service:jmx:rmi:///jndi/rmi://localhost:<jndi-remote-port>/jmxrmi
Example:
[x] Remote Process:
service:jmx:rmi:///jndi/rmi://localhost:15666/jmxrmi
9. ENJOY #8-]
Solution 2:
Adding -Djava.rmi.server.hostname='<host ip>'
resolved this problem for me.
Solution 3:
Tried with Java 8 and newer versions
This solution works well also with firewalls
1. Add this to your java startup script on remote-host:
-Dcom.sun.management.jmxremote.port=1616
-Dcom.sun.management.jmxremote.rmi.port=1616
-Dcom.sun.management.jmxremote.ssl=false
-Dcom.sun.management.jmxremote.authenticate=false
-Dcom.sun.management.jmxremote.local.only=false
-Djava.rmi.server.hostname=localhost
2. Execute this on your computer.
-
Windows users:
putty.exe -ssh user@remote-host -L 1616:remote-host:1616
-
Linux and Mac Users:
ssh user@remote-host -L 1616:remote-host:1616
3. Start jconsole
on your computer
jconsole localhost:1616
4. Have fun!
P.S.: during step 2, using ssh
and -L
you specify that the port 1616 on the local (client) host must be forwarded to the remote side. This is an ssh tunnel and helps to avoids firewalls or various networks problems.