Get GC log data from the Docker container using jstat - java

I have a java application running inside a docker container with OpenJDK11. I want to get GC data from this application using jstat tool (available inside a container). Any idea how can I achieve this from the host or another container running on the same host?
Thank you :)

The processes are visible on the host, so jstat -gcstat <pid> works on the host if you know the pid as it is seen by the host.
You can get the host-pid of a container-pid-1 via docker inspect -f '{{.State.Pid}}' <container name> and then walk the process tree (e.g. via /proc or some library encapsulating that logic) to find the java child process and then call jstat.
Another option is to (partially) join the container's namespace via nsenter or docker exec and then just execute jps and jstat inside the container. But that can be a security concern if you don't trust the container.

Related

Docker memory limits no taking effect for Java Apps in Centos 7 host

I am trying to deploy several Java (spring boot) apps in docker containers in 1 host, where I set memory limits (--memory=30m --memory-swap=50m) for each.
However when I check the limits using docker container stats, I see each container is using >400MB of the host's RAM. Due to this I cannot start all the containers I need as the kernel kills some of them (OOM).
What do I need to do to ensure that the containers' memory is controlled using the docker memory options?
My host is a digital ocean centos 7. Thanks
Main reason for this issue is that JRE is not aware it is running inside a container.
Let JVM detect how much memory is available in Docker container
https://blog.csanchez.org/2017/05/31/running-a-jvm-in-a-container-without-getting-killed
JAVA_OPTS="-server -Djava.net.preferIPv4Stack=true -XX:+UnlockExperimentalVMOptions -XX:+UseCGroupMemoryLimitForHeap -XX:MaxRAMFraction=1"
Make sure you have JDK 8-131 or above version
In case of JDK-9 it will be available to correctly detect available memory inside container.
Additional Referece: Docker run -m doesnt set the limit (JVM takes up the entire host machine's size for xms and xmx)
and
https://developers.redhat.com/blog/2017/03/14/java-inside-docker/

Fail to start H2o cluster in docker containers because it can not bind external or host ip

Now we try to use H2o to construct training cluster. It is easy to use by running java -jar ./h2o.jar and we can setup the cluster with simple flatfile.txt which contain multiple ip and ports.
But we found that it is impossible to setup the h2o cluster within docker containers. Although we can start multiple containers to run java -jar ./h2o.jar and add the prepared flatfile.txt, the h2o process will try to bind local(container's eth0) ip which is different from the one in flatfile.txt. We can java -jar ./h2o.jar -ip $ip to set the one which is in flatfile.txt but h2o instance is not able to run without this "external" ip.
If you use use "docker run --network=host ..." it will work.
See my response to a similar issue here. I describe how it is possible to start an H2O cluster using a flatfile and docker swarm. Basically, you have to run a script in each service before starting H2O, to identify the correct IP addresses for the cluster. This is because docker assigns two IPs to each service. The flatfile needs to use the $HOSTNAME IP for each cluster member, which is difficult to determine in advance.

Can I open custom hsperfdata_root/PID after process shutdown?

I'm using docker to containerize my application and want to look at it's performance from host machine. I've mapped volume : "/opt/tmp/my_app/:/tmp", which contains hsperfdata_root
Can I somehow open heap and other information from that hsperfdata_root/PID in jmap or some other tool ?
Does container must be in Running state for such debugging or it might be shutdown ?
The JDK includes the jstat tool for doing this. Try jstat -snap file:/tmp/hsperfdata_root.

Java Profiling - VisualVM

I invoke my Java application with different arguments from a shell script. Each time it binds to a different port. I am trying to use VisualVM to profile my application, but since it uses different ports for each invocation, I have to manually connect to the application every time from VisualVM GUI. Is there a way to do it more efficient?
You can always setup JMX for your app by setting System properties at startup:
java -Dcom.sun.management.jmxremote.port=1234\
-Dcom.sun.management.jmxremote.ssl=false \
-Dcom.sun.management.jmxremote.authenticate=false \
YourJavaApplication
Then you'll be able to store a profile in jvisualvm for connecting to that specific JMX port.

Why can't I attach jvisualvm to an instance of tomcat started from inside osx?

I'm starting tomcat from inside netbeans. I'd like to monitor the heap usage on that instance of tomcat so I fire up jVisualVM. However the process isn't listed. Any ideas?
Are you using Java version 6u24? Then you may fall victim to this bug which will be fixed in 6u25 (in a nutshell, jVisualVM can't find your process' hsperfdata).
Otherwise, you have to enable monitoring via JMX:
Pass the following JVM parameters to Tomcat:
-Dcom.sun.management.jmxremote.port=8888 -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=false
Then add the remote process to jVisualVM via File -> Add JMX Connection. You can connect to the process using port 8888
jVisualVM has some other gotchas, e.g. the user starting jVisualVM needs to be the same as the user owning the process you want to monitor (although, I don't think this is your issue). See more here.

Categories