java

[java] 자바의 가비지 콜렉션(GC: Garbage Collection)과 jstat을 이용한 모니터링

hs_seo 2019. 6. 4. 19:18

자바는 가비지 콜렉션 기능을 이용해 메모리 관리의 효율성을 제공합니다.

 

자바의 가비지 콜렉션은 'weak generational hypothesis' 이론에 기반합니다. 이는 신규로 생성한 객체의 대부분은 금방 사용하지 않는 상태가 되고, 오래된 객체에서 신규 객체로의 참조는 매우 적게 존재한다는 것입니다. 이 이론에 기반하여 자바는 Young 영역과 Old 영역으로 메모리를 분할하고, 신규로 생성되는 객체는 Young 영역에 보관하고, 오래동안 살아남은 객체는 Old 영역에 보관합니다.

 

Young 영역은 Eden, S0, S1 영역으로 구분됩니다. 신규로 생성되는 객체는 Eden에 보관되고, Eden 영역이 100% 차게 되면 사용하지 않는 객체는 제거하고 사용되는 객체는 S0 영역으로 이동합니다. 이를 마이너 GC라고 합니다. 다시 Eden 영역에 신규로 생성되는 객체가 보관되고, Eden 영역이 100%가 되면 Eden 영영과 S0영역에서 사용하지 않는 객체는 제거하고, 남은 객체는 S1 영역으로 이동합니다. 이 또한 마이너 GC입니다. 이 작업을 반복하면서 오래동안 살아 남은 객체는 Old 영역으로 이동하게 됩니다. 마이너 GC는 JVM을 멈추지 않고 진행 합니다.

 

마이너 GC에서 Young영역에서 Old 영역으로 이동하는 기준이 되는 값은 -XX:MaxTenuringThreshold 옵션으로 설정합니다. 이 설정값을 넘어가면 Young 에서 Old 영역으로 이동합니다.

 

Old 영역에 마이너 GC의 결과로 살아 남은 객체들이 보관되다가 Old영역이 100%가 되면 메이저 GC(Full GC)가 발생합니다. JVM의 동작을 멈추고 Old 영역의 메모리를 정리하게 됩니다. 메이저 GC가 발생하면 프로그램의 동작이 멈추기 때문에 메이저 GC의 발생과 처리시간을 줄이는 것이 중요합니다.

GC 설정

GC를 처리하는 방식을 설정하는 방법은 다음과 같습니다. XX 옵션을 이용하여 프로그램 실행시점에 처리 방식을 설정할 수 있습니다.

# GC 방법 설정 
$ java -Xmx1000m -XX:+UseConcMarkSweepGC

GC 처리 방식

  • -XX:+UseSerialGC: 하나의 스레드를 이용하여 Young 영역과 Old 영역의 정리를 처리
  • -XX:+UseParallelGC: Young 영역의 정리에 다수의 스레드를 이용하여 처리
  • -XX:+UseParallelOldGC: Old 영역의 처리도 다수의 스레드를 이용하여 처리
  • -XX:+UseConcMarkSweepGC: 메이저 GC의 성능 향상을 위해 Old 영역의 정리를 Concurrent 방식으로 처리

GC 모니터링

GC 모니터링은 jstat을 이용합니다. 상세한 설정 및 설명은 오라클 홈페이지에서 확인 바랍니다. jstat 을 이용하는 방법은 다음과 같습니다.

$ jstat [유틸옵션] [PID] [반복 출력 시간]
# PID 129의 정보를 1초(1000)마다 반복 출력 
$ jstat -gcutil 129 1000

jstat 옵션

  • class: 클래스 로더의 통계정보 출력
  • compiler: JIT 컴파일러의 통계정보 출력
  • gc: GC힙의 통계정보 출력
  • gccapacity: 힙의 용량(capacity) 정보를 출력
  • gccause: GC 통계정보와 GC가 발생한 원인 출력
  • gcnew: new 영역의 정보 출력
  • gcnewcapacity:new 영역의 용량 정보 출력
  • gcold: old 영역과 meta 영역의 정보 출력
  • gcoldcapacity:old 영역의 용량 출력
  • gcmetacapacity:meta 영역의 용량 출력
  • gcutil: GC 통계정보 쳘력
  • printcompilation:컴파일 메소드 정보 출력

jstat 예제

각 옵션별 처리 결과는 다음과 같습니다.

$ jstat -class 16973
Loaded  Bytes  Unloaded  Bytes     Time   
 11589 23339.2      152   220.6       5.18

$ jstat -compiler 16973
Compiled Failed Invalid   Time   FailedType FailedMethod
   22084      3       0   115.46          1 sun/misc/URLClassPath getResource

$ jstat -gc 16973
 S0C    S1C    S0U    S1U      EC       EU        OC         OU       MC     MU    CCSC   CCSU   YGC     YGCT    FGC    FGCT     GCT   
8000.0 8000.0  0.0   807.7  64512.0  26615.7   161152.0   61238.5   76768.0 75677.1 7932.0 7654.6  38831   95.958  10      0.219   96.178

$ jstat -gccapacity 16973
 NGCMN    NGCMX     NGC     S0C   S1C       EC      OGCMN      OGCMX       OGC         OC       MCMN     MCMX      MC     CCSMN    CCSMX     CCSC    YGC    FGC 
 80512.0 341312.0  80512.0 8000.0 8000.0  64512.0   161152.0   682688.0   161152.0   161152.0      0.0 1118208.0  76768.0      0.0 1048576.0   7932.0  38831    10

$ jstat -gccause 16973
  S0     S1     E      O      M     CCS    YGC     YGCT    FGC    FGCT     GCT    LGCC                 GCC                 
  0.00  10.10  41.26  38.00  98.58  96.50  38831   95.958    10    0.219   96.178 Allocation Failure   No GC               

$ jstat -gcmetacapacity 16973
   MCMN       MCMX        MC       CCSMN      CCSMX       CCSC     YGC   FGC    FGCT     GCT   
       0.0  1118208.0    76768.0        0.0  1048576.0     7932.0 38831    10    0.219   96.178

$ jstat -gcnew 16973
 S0C    S1C    S0U    S1U   TT MTT  DSS      EC       EU     YGC     YGCT  
8000.0 8000.0    0.0  807.7  6   6 4000.0  64512.0  26615.7  38831   95.958

$ jstat -gcnewcapacity 16973
  NGCMN      NGCMX       NGC      S0CMX     S0C     S1CMX     S1C       ECMX        EC      YGC   FGC 
   80512.0   341312.0    80512.0  34112.0   8000.0  34112.0   8000.0   273088.0    64512.0 38831    10

$ jstat -gcold 16973
   MC       MU      CCSC     CCSU       OC          OU       YGC    FGC    FGCT     GCT   
 76768.0  75677.1   7932.0   7654.6    161152.0     61238.5  38831    10    0.219   96.178

$ jstat -gcoldcapacity 16973
   OGCMN       OGCMX        OGC         OC       YGC   FGC    FGCT     GCT   
   161152.0    682688.0    161152.0    161152.0 38831    10    0.219   96.178

$ jstat -gcutil 16973
  S0     S1     E      O      M     CCS    YGC     YGCT    FGC    FGCT     GCT   
  0.00  10.10  41.26  38.00  98.58  96.50  38831   95.958    10    0.219   96.178

$ jstat -printcompilation 16973
Compiled  Size  Type Method
   22084    626    1 sun/reflect/GeneratedMethodAccessor93 invoke

gcutil 예제

jstat -gcutil을 이용하면 현재 Young 영역과 Old 영역의 메모리 사용률을 확인할 수 있습니다.

  • S0 : S0 영역 사용율
  • S1 : S1 영역 사용율
  • E : Eden 영역 사용율
  • O : Old 영역 사용율
  • M : Meta 영역 사용율
  • CCS : Compressed Class Space 영역 사용율
  • YGC : Young 영역 GC 횟수
  • YGCT : Young 영역 GC에 걸린 시간
  • FGC : Full GC 횟수
  • FGCT : Full GC에 걸린 시간
  • GCT : GC에 걸린시간(YGCT + FGCT)
# PID 16973의 GC 상황을 1초(1000)마다 한번씩 출력 
$ jstat -gcutil 16973 1000
  S0     S1     E      O      M     CCS    YGC     YGCT    FGC    FGCT     GCT   
 97.46   0.00  21.86  99.55  98.68  96.82   3548  166.537     3    1.449  167.987
 97.46   0.00  60.18  99.55  98.68  96.82   3548  166.537     3    1.449  167.987
 97.46   0.00  96.35  99.55  98.68  96.82   3548  166.537     3    1.449  167.987
  0.00  98.61  30.60  99.73  98.68  96.82   3549  166.620     3    1.449  168.069
  0.00  98.61  67.84  99.73  98.68  96.82   3549  166.620     3    1.449  168.069
 97.25   0.00   0.00  99.94  98.68  96.82   3550  166.702     4    1.449  168.152
  0.00   0.00  22.28   3.73  98.61  96.69   3550  166.702     4    1.813  168.516
  0.00   0.00  57.87   3.73  98.61  96.69   3550  166.702     4    1.813  168.516
  0.00   0.00  93.27   3.73  98.61  96.69   3550  166.702     4    1.813  168.516

참고

JVM 메모리 구조와 JAVA OPTION 값 정리
Java jstat로 메모리 모니터링
Java GC의 원리
Java 의 GC는 어떻게 동작하나?
[JAVA] JVM GC 튜닝 정리중..
Garbage Collection 모니터링 방법
Garbage Collection 튜닝
JVM Internal
Java Garbage Collection
JAVA8 Permanent 영역은 어디로 가는가
오랜만에 Garbage Collection 정리
JVM의 Garbage Collection
JDK8 적용 후, 심각한 성능저하가 발생한다면?
JAVA Garbage Collection의 기초
JVM Internal
Java HotSpot Garbage Collection

반응형