Technical Note/SERVER PERFORMANCE

JDK에 포함된 jmap 명령으로 실행 중인 JVM의 heap 상태를 확인해보자.


먼저 실행중인 JVM의 프로세스 ID를 알아야 한다. JDK에 포함된 jps 명령을 사용하거나 "ps -ef | grep java"를 사용한다.

$ jps

14895 Bootstrap

20658 Jps


JVM의 heap 상태를 확인할 때는 -heap 옵션을 사용한다.

$ jmap -heap 14895

Attaching to process ID 14895, please wait...

Debugger attached successfully.

Server compiler detected.

JVM version is 20.2-b06


using thread-local object allocation.

Parallel GC with 4 thread(s)


Heap Configuration:

   MinHeapFreeRatio = 40

   MaxHeapFreeRatio = 70

   MaxHeapSize      = 1073741824 (1024.0MB)

   NewSize          = 1048576 (1.0MB)

   MaxNewSize       = 4294901760 (4095.9375MB)

   OldSize          = 4194304 (4.0MB)

   NewRatio         = 2

   SurvivorRatio    = 8

   PermSize         = 16777216 (16.0MB)

   MaxPermSize      = 268435456 (256.0MB)


Heap Usage:

PS Young Generation

Eden Space:

   capacity = 268500992 (256.0625MB)

   used     = 4983224 (4.752372741699219MB)

   free     = 263517768 (251.31012725830078MB)

   1.8559424912664755% used

From Space:

   capacity = 44695552 (42.625MB)

   used     = 0 (0.0MB)

   free     = 44695552 (42.625MB)

   0.0% used

To Space:

   capacity = 44695552 (42.625MB)

   used     = 0 (0.0MB)

   free     = 44695552 (42.625MB)

   0.0% used

PS Old Generation

   capacity = 715849728 (682.6875MB)

   used     = 49058464 (46.785797119140625MB)

   free     = 666791264 (635.9017028808594MB)

   6.853179107445299% used

PS Perm Generation

   capacity = 67895296 (64.75MB)

   used     = 67656232 (64.52201080322266MB)

   free     = 239064 (0.22798919677734375MB)

   99.64789313239021% used


Heap 설정과 각 Generation 별 사용 현황을 확인할 수 있다. 만약 Old Generation의 사용량이 지속적으로 증가한다면 memory leak을 의심할 수 있다. 


이 때, -histo 옵션으로 클래스별 객체 수와 메모리 사용량을 확인할 수 있다. 

$ jmap -histo:live 14895 | more


num     #instances         #bytes  class name

----------------------------------------------

   1:        146470       18465136  <constMethodKlass>

   2:        146470       12896024  <methodKlass>

   3:        136294       12627544  [C

   4:         29162        8543584  [B

   5:         13655        7868184  <constantPoolKlass>

   6:        157523        7785024  <symbolKlass>

   7:         13655        5912264  <instanceKlassKlass>

   8:         10783        4518792  <constantPoolCacheKlass>

   9:        136440        3274560  java.lang.String

  10:         27292        2066056  [Ljava.util.HashMap$Entry;

  11:         20292        1623360  java.lang.reflect.Method

  12:         31501        1570240  [I

  13:         14653        1406688  java.lang.Class

  14:         23864        1336384  org.objectweb.asm.Label

  15:         27767        1332816  org.objectweb.asm.Item

  16:         39861        1275552  java.util.LinkedHashMap$Entry

  17:         53115        1274760  org.objectweb.asm.Edge

  18:         21894        1226064  org.objectweb.asm.Label

  19:         25335        1216080  org.objectweb.asm.Item   


주기적으로 클래스별 객체 수와 메모리 사용량을 체크해보면 어느 클래스의 객체가 누수되고 있는지 쉽게 알 수 있다. 하지만, 어디에서 누수를 일으키는지는 jmap 만으로는 알 수 없고, heap dump를 떠서 분석해야 알 수 있다.


이제 -dump 옵션으로 heap dump를 뜬 후, MAT 등으로 분석한다.

 $jmap -dump:format=b,file=heap.14895.hprof 14895

[출처] jmap으로 JVM heap 상태 확인|작성자 소프