How to connect a Java profiler like VisualVm or JConsole to a remote tomcat running on Amazon EC2

I have been having some issues related to heap space in a tomcat that I have been running on an Amazon EC2 instance.
In order to analyze the problem I wanted to connect a Java profiler to a remote tomcat.

This is my environment:

Application server: apache-tomcat-8.0.24
Instance type: EC2 t2.micro with ubuntu 14.04
java profiler: VisualVm and JConsole

After reading different tutorials and trying different approaches which didn’t work, here is what it worked for me:

1. Set the environment variables for tomcat

If you don’t have a set environment (setenv.sh) file, create one. In your tomcat folder/bin: create a sentenv.sh file and add execution rights.
eg:
[Shell]
cd /var/local/apache-tomcat-8.0.24/bin
touch setenv.sh
chmod +x setenv.sh
[/Shell]

2. Choose a free port for JMX and set the JMX configuration

In the setenv.sh file that you have created in the previous step you will need to add the followind configuration to CATALINA_OPTS:

-Dcom.sun.management.jmxremote
-Dcom.sun.management.jmxremote.port= RANDOM_JMX_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

In my configuration I have chosen randomly the 10005 as my jmx port, so my setenv.sh file looks like:
[Shell]
CATALINA_OPTS=”$CATALINA_OPTS -Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port=10005 -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.local.only=false -Djava.rmi.server.hostname=localhost”
[/Shell]
*Note: Use CATALINA_OPTS instead of JAVA_OPTS. If you use JAVA_OPTS you will get a java.net.BindException: Address already in use.
This is because with this options JAVA_OPTS will try to start a jmx server when you start and when you shutdown tomcat. Nevertheless, if you use CATALINA_OPTS will only run when you start tomcat.

3. Restart tomcat

4. Find the Java server RMI port

When you start tomcat in the server, Java will open a TCP port for RMI calls.
This port by default is 1099 but every time you start a new Java process it will open randomly a different port.

This port is important because it will allow us to connect to the Java Virtual Machine in the server, and later on we will need to redirect it via SSH tunnel.

To obtain the port run the following command:
[Shell]
sudo netstat -lp | grep or sudo netstat -lp | grep java
[/Shell]
rmi

As you can see the jmx port is 10005 and the RMI server port is 45995.

5. Create a SSH-tunnel to the JMX and RMI ports

By creating a ssh tunnel we won’t need to add any security group to the ec2 instance and we will be able to skip the firewall.
In your local machine create a ssh tunnel to the RMI port and to your JMX port using the following command:
[Shell]
ssh -N -v -L 45995:127.0.0.1:45995 -L 10005:127.0.0.1:10005 ubuntu@ec2xxxxx.compute.amazonaws.com -i
[/Shell]
this will work for Linux and Mac users but if you are running under Windows you will need to use putty.

6. Launch the profiler

In Visualvm add a jmx connection using the following uri:
service:jmx:rmi:///jndi/rmi://localhost:10005/jmxrmi

visualvm

or if you would like to use JConsole add the same uri in the remote field:
jconsole

After all, you will be able to run a profiler an analyze your remote application.

You may also like...

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.