How to activate JMX on my JVM for access with jconsole?
Solution 1
The relevant documentation can be found here:
http://java.sun.com/javase/6/docs/technotes/guides/management/agent.html
Start your program with following parameters:
-Dcom.sun.management.jmxremote
-Dcom.sun.management.jmxremote.port=9010
-Dcom.sun.management.jmxremote.rmi.port=9010
-Dcom.sun.management.jmxremote.local.only=false
-Dcom.sun.management.jmxremote.authenticate=false
-Dcom.sun.management.jmxremote.ssl=false
For instance like this:
java -Dcom.sun.management.jmxremote \
-Dcom.sun.management.jmxremote.port=9010 \
-Dcom.sun.management.jmxremote.local.only=false \
-Dcom.sun.management.jmxremote.authenticate=false \
-Dcom.sun.management.jmxremote.ssl=false \
-jar Notepad.jar
-Dcom.sun.management.jmxremote.local.only=false
is not necessarily required
but without it, it doesn't work on Ubuntu. The error would be something like
this:
01 Oct 2008 2:16:22 PM sun.rmi.transport. customer .TCPTransport$AcceptLoop executeAcceptLoop
WARNING: RMI TCP Accept-0: accept loop for ServerSocket[addr=0.0.0.0/0.0.0.0,port=0,localport=37278] throws
java.io.IOException: The server sockets created using the LocalRMIServerSocketFactory only accept connections from clients running on the host where the RMI remote objects have been exported.
at sun.management.jmxremote.LocalRMIServerSocketFactory$1.accept(LocalRMIServerSocketFactory.java:89)
at sun.rmi.transport. customer .TCPTransport$AcceptLoop.executeAcceptLoop(TCPTransport.java:387)
at sun.rmi.transport. customer .TCPTransport$AcceptLoop.run(TCPTransport.java:359)
at java.lang.Thread.run(Thread.java:636)
see http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6754672
Also be careful with -Dcom.sun.management.jmxremote.authenticate=false
which
makes access available for anyone, but if you only use it to track the JVM on
your local machine it doesn't matter.
Update:
In some cases I was not able to reach the server. This was then fixed if I set this parameter as well: -Djava.rmi.server.hostname=127.0.0.1
Solution 2
Running in a Docker container introduced a whole slew of additional problems for connecting so hopefully this helps someone. I ended up needed to add the following options which I'll explain below:
-Dcom.sun.management.jmxremote=true
-Dcom.sun.management.jmxremote.local.only=false
-Dcom.sun.management.jmxremote.authenticate=false
-Dcom.sun.management.jmxremote.ssl=false
-Djava.rmi.server.hostname=${DOCKER_HOST_IP}
-Dcom.sun.management.jmxremote.port=9999
-Dcom.sun.management.jmxremote.rmi.port=9998
DOCKER_HOST_IP
Unlike using jconsole locally, you have to advertise a different IP than you'll probably see from within the container. You'll need to replace ${DOCKER_HOST_IP}
with the externally resolvable IP (DNS Name) of your Docker host.
JMX Remote & RMI Ports
It looks like JMX also requires access to a remote management interface (jstat) that uses a different port to transfer some data when arbitrating the connection. I didn't see anywhere immediately obvious in jconsole
to set this value. In the linked article the process was:
- Try and connect from
jconsole
with logging enabled - Fail
- Figure out which port
jconsole
attempted to use - Use
iptables
/firewall
rules as necessary to allow that port to connect
While that works, it's certainly not an automatable solution. I opted for an upgrade from jconsole to VisualVM since it let's you to explicitly specify the port on which jstatd
is running. In VisualVM, add a New Remote Host and update it with values that correlate to the ones specified above:
Then right-click the new Remote Host Connection and Add JMX Connection...
Don't forget to check the checkbox for Do not require SSL connection
. Hopefully, that should allow you to connect.
Solution 3
Note, Java 6 in the latest incarnation allows for jconsole to attach itself to a running process even after it has been started without JMX incantations.
If that is available to you, also consider jvisualvm as it provides a wealth of information on running processes, including a profiler.
Solution 4
I'm using WAS ND 7.0
My JVM need all the following arguments to be monitored in JConsole
-Djavax.management.builder.initial=
-Dcom.sun.management.jmxremote
-Dcom.sun.management.jmxremote.port=8855
-Dcom.sun.management.jmxremote.authenticate=false
-Dcom.sun.management.jmxremote.ssl=false
Solution 5
On Linux, I used the following params:
-Djavax.management.builder.initial=
-Dcom.sun.management.jmxremote
-Dcom.sun.management.jmxremote.port=9010
-Dcom.sun.management.jmxremote.local.only=false
-Dcom.sun.management.jmxremote.authenticate=false
-Dcom.sun.management.jmxremote.ssl=false
and also I edited /etc/hosts
so that the hostname resolves to the host address (192.168.0.x) rather than the loopback address (127.0.0.1)
Related videos on Youtube
Mauli
My favourite language is Python, although for work I have to program in Java (Spring, Hibernate, OpenSCADA).
Updated on January 23, 2022Comments
-
Mauli over 2 years
How to activate JMX on a JVM for access with jconsole?
-
Mauli almost 15 yearsit is allowd, and actually it is only a reminder for me, because I always forget where to copy the parameters from and now I know where I find it :-)
-
Tim Büthe almost 10 yearsStack Exchange has always explicitly encouraged users to answer their own questions, see here: stackoverflow.com/help/self-answer
-
Mike Miller over 9 yearsMore than once I have searched SO for something and found a question answered... by myself. And one of those was asked by me as well. This is why it is good to put your own answers in. Also, think of all the other people that may have encountered your problem, if you answer your question you will be helping them too.
-
Andrew Johnston almost 9 yearsUpdated doc for Java 8 is here
-
kevinarpe over 8 years@Mauren: Can you provide a reference to your closed question you answered yourself? It might be worth discussing on Meta.
-
Mauren over 8 years@kevinarpe I'm sorry. This has been a long time ago and I'm no longer able to provide you with the link and content.
-
numéro6 almost 7 yearsQuestion should mention you may have the exact same problem when jvisualvm tells you "Failed to create JMX connection to target application" when trying to start CPU sampling.
-
-
LenW over 11 yearsThe -Dcom.sun.management.jmxremote.local.only=false is needed on Centos now as well
-
Gray about 10 yearsThis only works if you are running jconsole on the same host as the JVM you are trying to monitor.
-
amacleod over 9 yearsWhat is the expected behavior if you forget
-Dcom.sun.management.jmxremote.ssl=false
? Shouldjconsole
show an error, or would it just quietly fail to connect? -
Captain_spack_jarrow almost 9 yearsYes your answer worked for me (JDK 1.7, windows 8.1 64 bit)
-
Captain_spack_jarrow almost 9 years@ Thorbjorn If i start my java program without any parameters and try to connect with jconsole, I see in my program in the list but when I try to connect it fails. I think it is because of lack of SSL certificates. I just wanted to see the demo hence I had to use the parameters specified in the answer by user3013578 and it worked for me (JDK 1.7 , Windows 8.1, 64 bit).
-
matbrgz almost 9 yearsThe attach API requires jconsole to have the same 32/64 bit JVM as the launched program on some platforms.
-
kevinarpe over 8 yearsNit pick: It's weird to me that
com.sun.management.jmxremote
has the default value astrue
. (Thank you Sun!) To be super clear, especially to those less familiar with JMX nobs, I use:com.sun.management.jmxremote=true
Ref: docs.oracle.com/javase/8/docs/technotes/guides/management/… -
kevinarpe over 8 yearsIs it possible to disable this behaviour?
-
Orhun D. about 7 years"-Djava.rmi.server.hostname" worked like a charm for me !
-
numéro6 almost 7 yearsWas using Ubuntu 14.04 and everything worked out-of-the-box. Moved to Debian jessie and I had to do everything explained in this answer
-
Nikhil Owalekar over 6 yearssetting the hostname to localhost is very important if you are trying to connect a to a remote server through SSH tunnel, which is a very common case.
-
Carmageddon over 5 yearsThat works only if I disable the firewall on the server. I opened the port 9010/tcp in this example of course, I also tried to add
Dcom.sun.management.jmxremote.rmi.port=9011
and open in firewall - still cant connect with the firewall being up. Any thoughts? Have I missed anything? -
Thorsten Schöning about 5 years@Carmageddon
-Dcom.sun.management.jmxremote.rmi.port=[...]
in combination with-Djava.rmi.server.hostname=[...]
should work. Without those both I ran into similar issues, so make sure that your configured port for.rmi.port
is really accessible by your client AND the same for the configured.hostname
! Without the latter explicitly defined, Java will assume some IP it things is the primary interface of the server, which might still be blocked in your firewall. Without the port it assumes some random one. You might use Wireshark or Process Monitor to debug connections of client/server. -
Thorsten Schöning about 5 years
java.rmi.server.hostname
The value of this property represents the host name string that should be associated with remote stubs for locally created remote objects, in order to allow clients to invoke methods on the remote object. The default value of this property is the IP address of the local host, in "dotted-quad" format. docs.oracle.com/javase/8/docs/technotes/guides/rmi/… -
Thorsten Schöning about 5 years
-Djava.rmi.server.hostname=localhost
-Dcom.sun.management.jmxremote.rmi.port=[...]
is as well the key in case of tunnelling JMX/RMI through SSH. Without those, remote objects are accessed using the public/main/... IP of the server using some random port, which can't be forwarded easily. -
raisercostin almost 5 yearsI can confirm that you really need to use the external to container IP. For example it doesn't work with
-Djava.rmi.server.hostname=0.0.0.0
-
Barney over 4 yearsI didn't need to use
DOCKER_HOST_IP
anywhere - I just usedlocalhost
and forwarded the ports when running the docker image:-p 9998:9998, -p 9999:9999
etc. -
Gorgon_Union over 4 yearsShould you be able to see the port 1234 in use by jmx once you run this?
sudo lsof -i:1234
is not showing anything for me -
Edenshaw about 4 yearsIn case you already have access to the server using ssh, you don't need to mess with the firewall, just create a bridge:
ssh -g -L <local-port-in-your-machine-to-map>:localhost:<remote-server-jmx-port> <linux-username>@<remote-server-ip>
. Example:ssh -g -L 9523:localhost:9523 [email protected]
then go to thejvisualvm
and add a JMX connection aslocalhost:9523
. Don't forget to add:-Djava.rmi.server.hostname=127.0.0.1
in your remote server, because without it, it won't work. -
Webchen about 3 yearsThis also worked for my Docker-Java-Setup. It would be easier to mention that the
jstatd
port is equivalent to the-Dcom.sun.management.jmxremote.rmi.port
parameter. It is not explicitly stated, but it would improve the quality of your answer. Thanks!