Middleware/Tuning

Java Heap 메모리 옵션

Cloud Applicaiton Architect 2021. 7. 26. 13:46
반응형

JVM의 메모리 영역은 Runtime Data Areas내에 그 기능에 따라 5가지 영역으로 나뉘어 있는데 그 중에서도 new 키워드를 통해 객체를 생성하고 모든 개체와 해당 인스턴스 변수 및 배열이 저장되는 영역을 Heap 영역이라 한다.

Heap 메모리 구조(JDK 8이하)

 

(참고) JVM 7 과 JVM 8의 비교

 

또한 이 Heap 영역은 다시 그 기능에 따라 Eden, Servivor0, Servivor1, Old, Permenant 등으로 그 영역이 세분화 되며 이 Heap 영역에서 참조하는 변수나 필드가 존재하지 않으면 GC의 대상이 된다. 

이러한 GC는 Minor GC와 Major GC로 나뉜다.

Minor GC : New 영역에서 일어나는 GC

  1. 최초에 객체가 생성되면 Eden영역에 생성된다.
  2. Eden영역에 객체가 가득차게 되면 첫 번째 GC가 일어난다.
  3. survivor1 영역에 Eden영역의 메모리가 그대로 복사된다. 그리고 survivor1 영역을 제외한 다른 영역의 객체를 제거한다.
  4. Eden영역도 가득차고 survivor1영역도 가득차게된다면, Eden영역에 생성된 객체와 survivor1영역에 생성된 객체 중에 참조되고 있는 객체가 있는지 검사한다.
  5. 참조 되고있지 않은 객체는 내버려두고 참조되고 있는 객체만 survivor2영역에 복사한다.
  6. survivor2영역을 제외한 다른 영역의 객체들을 제거한다.
  7. 위의 과정중에 일정 횟수이상 참조되고 있는 객체들을 survivor2에서 Old영역으로 이동시킨다.
  8. 위 과정을 계속 반복, survivor2영역까지 꽉차기 전에 계속해서 Old로 비움

 

Major GC(Full GC) : Old 영역에서 일어나는 GC

  1. Old 영역에 있는 모든 객체들을 검사하며 참조되고 있는지 확인한다.
  2. 참조되지 않은 객체들을 모아 한 번에 제거한다.
  3. Minor GC보다 시간이 훨씬 많이 걸리고 실행중에 GC를 제외한 모든 쓰레드가 중지한다.

 

JVM 메모리 설정

Java 7이하의 JVM 메모리 구조 및 옵션은 아래와 같다.

JVM 7이하 Heap 메모리 구조 및 옵션

 

상기 JVM 메모리 구조는 Java 8부터 아래의 그림과 같은 구조로 변경되었다.

 

JVM 8이상 Heap 메모리 구조 및 옵션

 

※ JVM 8 Heap 메모리 구조

Java 8 이전에는 Metaspace 영역이 아닌 Permanent 영역이 존재하였다. Permanent 영역은 Class의 Meta 정보나 Method의 Meta 정보, Static 변수와 상수 정보들이 저장되는 공간으로 활용되었다. 하지만 Java 8 버전부터는 기존의 Permanent 영역이 Native 영역으로 이동하여 Metaspace 영역으로 변경되었다.

 

Eden Space [Young Generation]

 처음 생성된 모든 객체는 에덴 영역에 존재합니다. JVM에 의해 정해진 임계치에 도달하면 minor gc가 수행됩니다. minor gc가 수행되면 참조되지 않는 객체들은 에덴 영역에서 제거되고, 살아남은 객체들은 'From' 영역에서 'To' 영역의 Survivor 영역으로 이동합니다. gc가 끝나고나면 'From'과 'To' Survivor 영역의 역할이 서로 바뀝니다. ('From'은 'To'가 되고, 'To'는 'From'이 됩니다.)

  • 새롭게 생성된 객체 대부분이 이 영역으로 위치한다.
  • 대부분의 객체가 금방 접근 불가능 상태가 되기 때문에 매우 많은 객체가 Young 영역에 생성되었다가 사라진다.
  • 이 곳이 가득차면 minor gc가 발생한다.
  • minor gc가 발생하면 살아있는 객체들만 체크하고 나머지는 다 없애버린다.
  • 살아남은 객체들 중 더 오래 쓸 것 같은 것들은 Tenured 영역으로 옮긴다.

 

Survivor 1 (From)

 이 영역은 에덴 영역으로부터 살아남은 객체가 담깁니다. 이전의 gc 과정에서는 'To'의 역할을 하던 영역입니다.

 

Survivor 2 (To)

 이 영역은 gc가 수행될 때, 에덴 영역과 'From'의 역할을 하던 Survivor 영역에서 살아남은 객체들이 담깁니다.

 

Tenured [Old Generation]

 Survivor 영역의 객체가 minor gc에서 살아남아 다른 Survivor 영역으로 이동할 때마다 객체의 Age가 증가합니다. 이 Age가 일정 이상이 되면 Tenured 영역으로 이동하게 됩니다(Promotion).

Promotion의 기준이 되는 Age는 -XX:MaxTenuringThreshold 옵션으로 설정할 수 있습니다. Java SE 8 에서의 default 값은 15이며, 설정 가능한 범위는 0 ~ 15 입니다.

  • Young 영역에서 살아남은 객체들은 이 곳으로 복사된다.
  • 이 곳이 가득차면 major gc(혹은 full gc)가 발생한다.
  • 대부분 Young 영역보다 크게 할당하며, 크기가 큰 만큼 Young 영역보다 gc는 적게 발생한다.
  • major gc는 minor gc 보다 오래걸린다.

 

전체 Heap 메모리 크기 설정

-Xms : 초기 JVM이 생성될때 설정한 Heap 메모리 값
-Xmx : JVM이 최대 사용 가능한 Heap 메모리 값

e.g. -Xms1200m –Xmx1200m
  • Heap 메모리는 WAS의 경우 통상 2GB~4GB 정도가 설정되며, 독립 실행 배치는 125MB~256MB 정도 설정하고 부득이 한 경우 그 이상으로 설정
  • 대량 데이터를 로드하여 분석하는 시스템 같은 경우 10GB 이상도 설정하기도 함
  • New 영역을 별도로 설정하지 않는 경우가 많으나 응답시간이 짧은 경우 New 영역을 늘려주면 Full GC 발생 횟수를 줄일 수 있음

 

New 영역 크기 설정

-XX:New Size=000m 000에 new에 할당할 메모리 값 기술

e.g. -XX:NewSize=512m

 

New Old간에 메모리 비율 설정

-XX:NewRatio=x    x 비율

e.g. -XX:NewRatio=2    ---> Yong:Old 비율이 1:2이라는 의미 

 

New 영역 내부의 Eden, Survivor 영역비

-XX:SurvivorRatio 

e.g. -XX:SurvivorRatio=8
--->  Young 전제 2GB 에서 SurvivorRatio가 8이면 Eden영역이 1.6GB
        Survivor영역이 0.4GB이고 Survivor 영역은 S1,S2로 2개의 영역으로
       이루어져 있으므로 각각 0.2GB, 결과적으로 Eden과 Survivor 비율은 1:8
  • Survivor 영역 크기 = New 영역 전체 / (SurvivorRatio + 2)
  • UseAdaptiveSizePolicy는 New영역, Eden, Survivor 비율을 동적으로 조정하는 옵션
  • -XX:-UseAdaptiveSizePolicy 처리하여 빈번한 GC로 성능 저하 방지

 

Perm 영역 크기(JDK 1.8부터 삭제)

-XX:PermSize=64m

e.g. -XX:MaxPermSize=64m

 

Metaspace 영역 크기

-XX:MetaspaceSize=256m

-XX:MaxMetaspaceSize=256m

 

Heap Dump 생성

-XX:+HeapDumpOnOutOfMemoryError
-XX:HeapDumpPath=/logs001/java/heapdump/

 

JVM 옵션 요약(JDK 8.0 이상)

-server
-Xms<heap size>[g|m|k] 
-Xmx<heap size>[g|m|k]
-XX:MaxMetaspaceSize=<metaspace size>[g|m|k]
-Xmn<young size>[g|m|k]
-XX:SurvivorRatio=<ratio>
-XX:+UseConcMarkSweepGC 
-XX:+CMSParallelRemarkEnabled
-XX:+UseCMSInitiatingOccupancyOnly 
-XX:CMSInitiatingOccupancyFraction=<percent>
-XX:+ScavengeBeforeFullGC 
-XX:+CMSScavengeBeforeRemark
-XX:+PrintGCDateStamps -verbose:gc 
-XX:+PrintGCDetails 
-Xloggc:"<path to log>"
-XX:+UseGCLogFileRotation 
-XX:NumberOfGCLogFiles=10 
-XX:GCLogFileSize=100M
-Dsun.net.inetaddr.ttl=<TTL in seconds>
-XX:+HeapDumpOnOutOfMemoryError 
-XX:HeapDumpPath=<path to dump>`date`.hprof
-Djava.rmi.server.hostname=<external IP>
-Dcom.sun.management.jmxremote.port=<port> 
-Dcom.sun.management.jmxremote.authenticate=false 
-Dcom.sun.management.jmxremote.ssl=false

 

반응형

'Middleware > Tuning' 카테고리의 다른 글

JVM 옵션을 통한 성능 튜닝 이해  (0) 2021.08.13
Java GC 알고리즘 및 주요 옵션  (0) 2021.07.28
Java JVM 구조  (0) 2021.07.26