I was trying to start JFR on a production java application, however I was getting this error:
root@798db95bcd-2wnsk:/# jcmd 51 JFR.start filename=/tmp/myrecording.jfr
51:
com.sun.tools.attach.AttachNotSupportedException: Unable to open socket file /proc/51/root/tmp/.java_pid51: target process 51 doesn't respond within 10500ms or HotSpot VM not loaded
at jdk.attach/sun.tools.attach.VirtualMachineImpl.<init>(VirtualMachineImpl.java:104)
at jdk.attach/sun.tools.attach.AttachProviderImpl.attachVirtualMachine(AttachProviderImpl.java:58)
at jdk.attach/com.sun.tools.attach.VirtualMachine.attach(VirtualMachine.java:207)
at jdk.jcmd/sun.tools.jcmd.JCmd.executeCommandForPid(JCmd.java:113)
at jdk.jcmd/sun.tools.jcmd.JCmd.main(JCmd.java:97)
The Java application runs in a Jar, within a Docker container in Kubernetes. De Java runs under a different user than root. Java does not care if you are root, it requires that you start JFR with the same user
as the user of the java process.
So in my case I was running the application with uer appuser:
su -c "$JAVA_HOME/bin/jcmd 51 JFR.start filename=/tmp/myrecording.jfr" -s /bin/sh appuser
So in the command above, 51 is the java pid which you can determine by calling jps
In order to dump a JFR file run this:
su -c "$JAVA_HOME/bin/jcmd 51 JFR.dump filename=/tmp/myrecording.jfr" -s /bin/sh appuser
To stop JFR:
su -c "$JAVA_HOME/bin/jcmd 51 JFR.stop name=51" -s /bin/sh appuser
To copy the jfr file from the Kubernetes pod to your local machine:
kubectl cp pod-name-798db95bcd-qzjtj:/tmp/myrecording.jfr ./myrecording.jfr -n mynamespace
Some kubectl commands I always forget:
Get the current kubectl context:
kubectl config current-context
Get all configured Kubernetes contexts:
kubectl config get-contexts
Set the current context:
kubectl config use-context my-context
More JFR stuff: https://docs.oracle.com/javacomponents/jmc-5-5/jfr-command-reference/diagnostic-command-reference.htm#resourceid-15322-48C8362A
Finally:
Good luck profiling with JDK Mission Control