JVM strumenti di diagnostica

jcmd

Spesso, quando viene realizzata un’applicazione, sarebbe buona abitudine effettuare i necessari tests di performance ,  endurance e  stress, in modo da rilevare eventuali punti critici o di miglioramento prima che l’applicazione , come si dice in gergo, venga messa in produzione. Nel caso di un’applicazione Java, occorre poter interagire con la JVM. Esistono diversi tolls e/o utility, uno di questi è jcmd che viene utilizzato per invocare comandi di diagnostica alla JVM (qui il riferimento ufficiale). Per scoprire i comandi che possiamo eseguire è sufficiente procedere come segue :

jcmd <pid> help

The following commands are available:
VM.native_memory
ManagementAgent.stop
ManagementAgent.start_local
ManagementAgent.start
GC.rotate_log
Thread.print
GC.class_stats
GC.class_histogram
GC.heap_dump
GC.run_finalization
GC.run
VM.uptime
VM.flags
VM.system_properties
VM.command_line
VM.version

In realtà, la disponibilità di un comando, piuttosto che un altro, dipende anche dalla JVM su cui operiamo (in questo caso si tratta di openjdk-1.8.0.77-0).

Un comando  molto utile è il seguente :

jcmd <pid> VM.system_properties

ci permette di visionare tutte le system properties dell’applicativo che gira nella jvm

jcmd <pid> GC.heap_dump /tmp/test.hprof

permette di generare il dump dello heap che possiamo dare in pasto ad eventuali tools di analisi.

Infine, un comando che, secondo me, vale la pena tenere presente è

jcmd <pid> GC.run

Questo ci permette di forzare una System.gc() all”interno della JVM ed è, quindi, utilissimo per verificare che la memoria venga effettivamente liberata a seguito di un full gc. Ovviamente, per procedere, con tale osservazione occorre abilitare la nostra JVM a stampare l’andamento del gc.log.  Questo si può banalemente attivare aggiungendo le seguenti options sulla linea di comando che istanzia la jvm :

-XX:+PrintGC -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -Xloggc:gc.log

JMX PORT dove si trova configurata in WildFly

Accedere al file standalone.xml.
<socket-binding-group name="standard-sockets" default-interface="public" port-offset="${jboss.socket.binding.port-offset:500}">
<socket-binding name="management-http" interface="management" port="${jboss.management.http.port:9990}"/>
<socket-binding name="management-https" interface="management" port="${jboss.management.https.port:9993}"/>
<socket-binding name="ajp" port="${jboss.ajp.port:8009}"/>
<socket-binding name="http" port="${jboss.http.port:8080}"/>
<socket-binding name="https" port="${jboss.https.port:8443}"/>
.....
<socket-binding-group>

Per capire quale porta utilizzare è sufficiente aggiungere l’offset definito, nel nostro caso “500” al valore standard indicato ovvero “9990”.

Questo significa che nel nostro caso occorre utilizzare alla porta

9990+500 = 10490