52

Can I check heap usage of a running JVM from the commandline, I mean the actual usage rather than the max amount allocated with Xmx.

I need it to be commandline because I don't have access to a windowing environment, and I want script based on the value , the application is running in Jetty Application server

Jacek Laskowski
  • 72,696
  • 27
  • 242
  • 420
Paul Taylor
  • 13,411
  • 42
  • 184
  • 351

5 Answers5

66

You can use jstat, like :

 jstat -gc pid

Full docs here : http://docs.oracle.com/javase/7/docs/technotes/tools/share/jstat.html

Danny Kirchmeier
  • 1,134
  • 6
  • 14
Mark
  • 2,423
  • 4
  • 24
  • 40
  • Thankyou looks like what I want, might take a while to understand all the options though, I was basically looking for how much of the heap is used – Paul Taylor Jan 22 '13 at 17:55
  • 2
    so i think OU is the key column, with OC showing the max that was allocated – Paul Taylor Jan 23 '13 at 21:00
  • 6
    @PaulTaylor You want the EU and OU columns - adding them up gives you the amount of the heap that is used. Adding up the EC and OC columns gives you the amount allocated for the heap. – pacoverflow Jan 14 '15 at 22:01
  • how do you do this if jvm is running as one linux user and you login as another? – Kalpesh Soni Jun 29 '17 at 22:24
21

For Java 8 you can use the following command line to get the heap space utilization in kB:

jstat -gc <PID> | tail -n 1 | awk '{split($0,a," "); sum=a[3]+a[4]+a[6]+a[8]; print sum}'

The command basically sums up:

  • S0U: Survivor space 0 utilization (kB).
  • S1U: Survivor space 1 utilization (kB).
  • EU: Eden space utilization (kB).
  • OU: Old space utilization (kB).

You may also want to include the metaspace and the compressed class space utilization. In this case you have to add a[10] and a[12] to the awk sum.

Till Schäfer
  • 642
  • 6
  • 15
13

All procedure at once. Based on @Till Schäfer answer.

In KB...

jstat -gc $(ps axf | egrep -i "*/bin/java *" | egrep -v grep | awk '{print $1}') | tail -n 1 | awk '{split($0,a," "); sum=(a[3]+a[4]+a[6]+a[8]+a[10]); printf("%.2f KB\n",sum)}'

In MB...

jstat -gc $(ps axf | egrep -i "*/bin/java *" | egrep -v grep | awk '{print $1}') | tail -n 1 | awk '{split($0,a," "); sum=(a[3]+a[4]+a[6]+a[8]+a[10])/1024; printf("%.2f MB\n",sum)}'

"Awk sum" reference:

 a[1] - S0C
 a[2] - S1C
 a[3] - S0U
 a[4] - S1U
 a[5] - EC
 a[6] - EU
 a[7] - OC
 a[8] - OU
 a[9] - PC
a[10] - PU
a[11] - YGC
a[12] - YGCT
a[13] - FGC
a[14] - FGCT
a[15] - GCT

Used for "Awk sum":

a[3] -- (S0U) Survivor space 0 utilization (KB).
a[4] -- (S1U) Survivor space 1 utilization (KB).
a[6] -- (EU) Eden space utilization (KB).
a[8] -- (OU) Old space utilization (KB).
a[10] - (PU) Permanent space utilization (KB).

[Ref.: https://docs.oracle.com/javase/7/docs/technotes/tools/share/jstat.html ]

Thanks!

NOTE: Works to OpenJDK!

FURTHER QUESTION: Wrong information?

If you check memory usage with the ps command, you will see that the java process consumes much more...

ps -eo size,pid,user,command --sort -size | egrep -i "*/bin/java *" | egrep -v grep | awk '{ hr=$1/1024 ; printf("%.2f MB ",hr) } { for ( x=4 ; x<=NF ; x++ ) { printf("%s ",$x) } print "" }' | cut -d "" -f2 | cut -d "-" -f1

UPDATE (2021-02-16):

According to the reference below (and @Till Schäfer comment) "ps can show total reserved memory from OS" (adapted) and "jstat can show used space of heap and stack" (adapted). So, we see a difference between what is pointed out by the ps command and the jstat command.

According to our understanding, the most "realistic" information would be the ps output since we will have an effective response of how much of the system's memory is compromised. The command jstat serves for a more detailed analysis regarding the java performance in the consumption of reserved memory from OS.

[Ref.: http://www.openkb.info/2014/06/how-to-check-java-memory-usage.html ]

Eduardo Lucio
  • 1,771
  • 2
  • 25
  • 43
  • 1
    Why are you summing YGCT too? It's a time – Gamby Sep 03 '19 at 10:50
  • 2
    regarding your question: ps shows the allocated system memory and not the heap usage. Thus, java might allocate memory, which is unused. – Till Schäfer Jan 10 '20 at 14:10
  • 1
    the java pid retreaval will not work for multiple java processes. Its better to do somthink like `for pid in $(ps -o pid= -C java); do [...] done` or to use `jps -m` – Till Schäfer Jan 10 '20 at 14:15
  • @TillSchäfer I didn't really understand what you meant by `$(ps -o pid= -C java); do [...] done`... Could you show us a complete example of what you wanted to explain? So I can further enrich my answer. Thanks! =D – Eduardo Lucio Feb 16 '21 at 18:33
  • @Gamby Adjusted! Thanks! =D – Eduardo Lucio Feb 16 '21 at 18:43
  • @EduardoLucio your statement `$(ps axf | egrep -i "*/bin/java *" | egrep -v grep | awk '{print $1}')` is functionally equivalent to the much shorter `$(ps -o pid= -C java)`. The second one does only rely on ps (not egrep, awk), and does not rely on fixed paths of the java installation. Furthermore, jstat only accepts a singe vm pid. Thus, your command will fail for more than a single java instance. This is the reason you should loop over the pid of all running vms and execute the jstat command for each pid. – Till Schäfer Feb 17 '21 at 21:08
  • @TillSchäfer I don't know how to adapt this command `jstat -gc $(ps axf | egrep -i "*/bin/java *" | egrep -v grep | awk '{print $1}') | tail -n 1 | awk '{split($0,a," "); sum=(a[3]+a[4]+a[6]+a[8]+a[10])/1024; printf("%.2f MB\n",sum)}'` to use this excerpt `for pid in $(ps -o pid= -C java); do [...] done` that you showed us... Thanks and sorry about that! =D – Eduardo Lucio Feb 17 '21 at 23:03
9

If you start execution with gc logging turned on you get the info on file. Otherwise 'jmap -heap ' will give you what you want. See the jmap doc page for more.

Please note that jmap should not be used in a production environment unless absolutely needed as the tool halts the application to be able to determine actual heap usage. Usually this is not desired in a production environment.

Jacek Laskowski
  • 72,696
  • 27
  • 242
  • 420
Erik
  • 2,013
  • 11
  • 17
2

If you are using JDK 8 and above , use jcmd:

jcmd < pid > GC.heap_info