How to attach JConsole to a remote JVM? [duplicate] - java

This question already has answers here:
Has anyone ever got a remote JMX JConsole to work?
(20 answers)
Closed 7 years ago.
I have a Java 8 application running on a remote Linux server and need to attach a JConsole to it for debugging purposes.
From my local machine I set up a tunnel to the remote machine:
ssh -fN -L 9999:localhost:9999 myuser#1.11.11.111
On the remote machine I run the application with the following system properties:
java -Dcom.sun.management.jmxremote.port=9999 \
-Dcom.sun.management.jmxremote.authenticate=false \
-Dcom.sun.management.jmxremote.ssl=false \
-Dcom.sun.management.jmxremote.local.only=false \
-cp foo.jar:config com.foo.bar.Main config/blah.properties
but when I start the JConsole I get Secure connection failed.
If I click on "Insecure connection" I get
How can I get around this?

I managed to make it working adding an extra system property for the RMI port:
java \
-Dcom.sun.management.jmxremote.port=9999 \
-Dcom.sun.management.jmxremote.rmi.port=9999 \
-Dcom.sun.management.jmxremote.authenticate=false \
-Dcom.sun.management.jmxremote.ssl=false \
-Dcom.sun.management.jmxremote.local.only=false \
-cp foo.jar:config com.foo.bar.Main config/blah.properties

Related

JVM arguments not being passed to java application at run time

I try to give VM parameters (jmx parameters) to run a jar file. For some reason, the VM parameters configured not being passed to the java application at run time (log statement in main method confirms that aswell). Application launches successfully but unable to access jmx service. It all works fine with Intellij though.
JVM_OPTS="-Dcom.sun.management.jmxremote \
-Djava.rmi.server.hostname=localhost \
-Dcom.sun.management.jmxremote.port=8020 \
-Dcom.sun.management.jmxremote.rmi.port=8021 \
-Dcom.sun.management.jmxremote.authenticate=false \
-Dcom.sun.management.jmxremote.ssl=false"
eval "java $JVM_OPTS -Djava.security.egd=file:/dev/./urandom -jar target/shopfront-0.0.1-SNAPSHOT.jar"
I tried to access jmx via visual vm but I am unsuccessful.
Version: Java 11
I expect to access jmx via visual client
Any help is appreciated!
The above script works fine. It is bash script

How to connect to JMX server running inside WSL2

I'm running my Java application with the following parameters that enable JMX server's remote connections:
-Dcom.sun.management.jmxremote=true
-Dcom.sun.management.jmxremote.port=9998
-Dcom.sun.management.jmxremote.authenticate=false
-Dcom.sun.management.jmxremote.ssl=false
I can successfully connect to that JMX server via VisualVM by adding a new JMX Connection to address: <HOSTNAME>:9998
But when i run that application inside Windows Subsystem for Linux 2 (WSL2) Visual VM cannot connect to localhost:9998:
connection failed
For what I know, every port that the application is listening on in WSL2 is also opened in host machine (Windows itself), and I can check that using Win+R -> cmd -> telnet localhost 9998 (connected successfully).
Also, I'm running an nginx instance inside WSL2 that I can connect to by any browser on my host machine (Windows) using localhost.
I had the same problem and finally I found a working set of properties for my WSL2. Additionally I had additional requirement to set it up for docker container running inside WSL2, while JConsole/VisualVM was running on Windows host. I have also a VPN running which probably mess up networking even more.
I found this application https://github.com/cluther/jmx-tester to be useful in debugging the connection.
inside WSL2
java \
-Dcom.sun.management.jmxremote=true \
-Djava.rmi.server.hostname=127.0.0.1 \
-Dcom.sun.management.jmxremote.port=9991 \
-Dcom.sun.management.jmxremote.ssl=false \
-Dcom.sun.management.jmxremote.registry.ssl=false \
-Dcom.sun.management.jmxremote.authenticate=false \
-Djava.net.preferIPv4Stack=true \
-jar jmx-tester-1.0.0.jar
Then on Windows host connect JMX to 127.0.0.1:9991
docker container inside WSL2
java \
-Dcom.sun.management.jmxremote=true \
-Djava.rmi.server.hostname=127.0.0.1 \
-Dcom.sun.management.jmxremote.host=0.0.0.0 \
-Dcom.sun.management.jmxremote.port=9991 \
-Dcom.sun.management.jmxremote.rmi.port=9991 \
-Dcom.sun.management.jmxremote.ssl=false \
-Dcom.sun.management.jmxremote.registry.ssl=false \
-Dcom.sun.management.jmxremote.authenticate=false \
-Djava.net.preferIPv4Stack=true \
-jar jmx-tester-1.0.0.jar
Then on Windows host connect JMX to 127.0.0.1:9991
I wasn't able to get Windows jconsole to connect to a JVM running in WSL2 using any of the suggestions above, however it is now possible to run Linux jconsole in WSL2, using Windows 11's Linux GUI support. Works perfectly.
In my case it depends on java.net.preferIPv6Addresses https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/net/doc-files/net-properties.html
Default value is false
I have server running on WSL2 and client running on Win11:
c:>java -Djava.net.preferIPv6Addresses=system my.My2 http://localhost:8025
http://localhost:8025
{"timestamp":"2022-04-22T10:25:03.819+00:00","status":"404","error":"Not Found","path":"/"}
c:>java -Djava.net.preferIPv6Addresses=true my.My2 http://localhost:8025
http://localhost:8025
{"timestamp":"2022-04-22T10:25:14.544+00:00","status":"404","error":"Not Found","path":"/"}
c:>java -Djava.net.preferIPv6Addresses=false my.My2 http://localhost:8025
http://localhost:8025
Exception in thread "main" java.net.ConnectException
at java.net.http/jdk.internal.net.http.HttpClientImpl.send(HttpClientImpl.java:571)
at java.net.http/jdk.internal.net.http.HttpClientFacade.send(HttpClientFacade.java:123)
at my.My2.main(My2.java:15)
Caused by: java.net.ConnectException
...
c:>java my.My2 http://localhost:8025
http://localhost:8025
Exception in thread "main" java.net.ConnectException
at java.net.http/jdk.internal.net.http.HttpClientImpl.send(HttpClientImpl.java:571)
at java.net.http/jdk.internal.net.http.HttpClientFacade.send(HttpClientFacade.java:123)
at my.My2.main(My2.java:15)
Caused by: java.net.ConnectException
...
This seems to be a general issue with Java.
https://github.com/microsoft/WSL/discussions/6253
A workaround that worked for me was listening on '0.0.0.0' instead of '127.0.0.1' in WSL2 with the JMX server.

JMX and Debugging on Tomcat inside Docker

I am trying to setup IntelliJ to connect to a Tomcat instance running in a Docker container. I would like to be able to use remote debugging and also deploy remotely using JMX.
I can enable remote debugging using the environment variables
JPDA_ADDRESS=8000
JPDA_TRANSPORT=dt_socket
and by starting Tomcat with catalina.sh jpda run, so remote debugging works without a problem.
I can also do this alternatively with
CATALINA_OPTS='-agentlib:jdwp=transport=dt_socket,address=8000,suspend=n,server=y'
and then I don't need to use catalina.sh jpda run
No matter what I do, I cannot get JMX to work. I verified that I have catalina-jmx-remote.jar in /usr/local/tomcat/lib`.
I have tried setting CATALINA_OPTS and JAVA_OPTS to
-Dcom.sun.management.jmxremote
-Dcom.sun.management.jmxremote.local.only=false
-Dcom.sun.management.jmxremote.authenticate=false
-Dcom.sun.management.jmxremote.port=1099
-Dcom.sun.management.jmxremote.rmi.port=1099
-Djava.rmi.server.hostname=192.168.99.100
-Dcom.sun.management.jmxremote.ssl=false
I have verified that 192.168.99.100 is the IP of my docker machine. I have tried connecting to JMX with VisualJM and IntelliJ, it does not work. I have verified that the port 1099 is open and available from the host.
Tomcat is receiving the JMX args
20-Apr-2016 23:50:14.019 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: -Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.local.only=false -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.port=1099 -Dcom.sun.management.jmxremote.rmi.port=1099 -Djava.rmi.server.hostname=192.168.99.100 -Dcom.sun.management.jmxremote.ssl=false
Why can't I get JMX to work? There is no information available in any logs and this will not work no matter what I try.
Edit: lsof -i :1099 shows nothing running on that port
I am running on Mac OS X. It is a docker-machine but I believe docker uses virualbox on mac because it can't run containers natively.
I have mapped the port. docker ps shows 0.0.0.0:1099->1099/tcp, 0.0.0.0:8000->8000/tcp, 0.0.0.0:8080->8080/tcp. Ports 8080 and 8000 work so 1099 should be mapped correctly too.
I was able to connect when I used 0.0.0.0 for jmxremote.host and server.hostname
HOST=0.0.0.0
java -Xmn100M -XX:+PrintGCDetails -XX:MinHeapFreeRatio=20 -XX:MaxHeapFreeRatio=40 -Xmx384M $JAVA_OPTS\
-Dcom.sun.management.config.file=/opt/app/management.properties \
-Djava.util.logging.config.file=/opt/app/logging.properties \
-Dcom.sun.management.jmxremote.port=$JMX_PORT \
-Dcom.sun.management.jmxremote.rmi.port=$JMX_PORT \
-Dcom.sun.management.jmxremote.host=$HOST \
-Djava.rmi.server.hostname=$HOST \
-jar /opt/app/app.jar

Cannot connect to JMX/RMI server with VisualVM for no apparent reason

I have my OSGi application launching with the following command in my remote machine:
java -Dcom.sun.management.jmxremote \
-Dcom.sun.management.jmxremote.port=8080 \
-Dcom.sun.management.jmxremote.local.only=false \
-Dcom.sun.management.jmxremote.authenticate=false \
-Dcom.sun.management.jmxremote.ssl=false \
-jar bin/felix.jar
And in my local machine I have VisualVM from which I try to connect to the remote JVM instance:
What am I missing?
Thanks!
The comment from #Klara saved my day !!
fixed my connection to the jstad
jstatd -J-Djava.security.policy=all.policy -J-Djava.rmi.server.hostname=hostname-goes-here &

How to I trick Java RMI/JMX to be accessible from outside localhost without hardcoding the IP?

How can I trick Java RMI to be accessible from outside localhost without hardcoding the IP ?
As it is impossible to make RMI to bind to 0.0.0.0 the solution is to detect the IP and use it.
I used the solution below on both Linux and OS X:
IP=$(ifconfig | sed -En 's/127.0.0.1//;s/.*inet (addr:)?(([0-9]*\.){3}[0-9]*).*/\2/p')
# if we have several IPs found, we pick the first one
for IP in $IP:
do
break
done
CATALINA_OPTS="-Dcom.sun.management.jmxremote \
-Dcom.sun.management.jmxremote.port=8081 \
-Dcom.sun.management.jmxremote.local.only=false \
-Dcom.sun.management.jmxremote.authenticate=false \
-Dcom.sun.management.jmxremote.ssl=false \
-Djava.rmi.server.hostname=${IP} "
Obviously that's the insecure way to configure it, but you are free to tune it to fit your needs.

Categories

Resources