티스토리 뷰

728x90
반응형

포스팅은 HeapDump 분석 가이드입니다.


HeapDump는 Memory 누수를 진단하는데 중요한 역할을 하는 TroubleShooting 방법입니다. ThreadDump에서 확인한 Application의 상세 Stack을 확인할 수 있는 장애 진단에 매우 중요한 부분이라 볼수 있습니다.


먼저 HeapDump이 정의에 대해 알아보겠습니다.

Heap이란 Java에서 사용하는 object들을 저장하는 공간입니다.

Heap에는 java object 정보만 저장되는 것이 아니고 메타 정보 및 각 object들에 대한 참조 정보도 담겨 있습니다. Heap 메모리에 존재하는 모든 object는 Root 노드부터 시작해서 parent/child 형식의 tree 구조를 형성하고 있습니다. 이러한 tree 구조는 각 object들의 참조 정보를 통해 이루어집니다. tree 구조가 꼭 정형화된 top/down 방식의 구조로만 이루어지지 않고 간혹 역 참조에 의해 상호 참조가 발생하기도 합니다.

Heap의 정보를 분석하는 것은 java에서의 메모리 문제(각종 OutOfMemoryError 문제들)를 해결하기 위한 중요한 작업입니다.


실제 Heap dump를 통해 분석이 필요한 경우는 다음과 같습니다.

OutOfMemoryError에 대한 문제 분석 시 필요하다.

Heap dump로 할 수 있는 가장 중요하고도 기본적으로 해결할 수 있는 문제입니다.


Permanent Full에 대한 문제 분석 시 필요하다.

loaded Object의 메타정보들에 대한 정보를 분석 함으로써 Permanent Full 문제에 대한 분석이 가능합니다.

물론 Permanent Full도 일종의 OutOfMemoryError라고 할 수 있습니다.

 

메모리 Leak 문제 분석 시 필요하다.

메모리 Leak이 지속되면 OutOfMemoryError가 되지만 OutOfMemoryError가 발생하지 않고 많은 메모리를 점유하고 해제되지 않고 있어 GC의 빈도가 잦아져 문제가 발생되는 경우에 Heap dump를 통해 해제되지 않는 object들을 확인할 수 있습니다.

 

기타 Heap과 관련된 문제 분석 시 필요하다.

복합적인 원인으로 문제가 발생할 경우 문제 분석을 위한 하나의 정보로서 Heap dump를 활용할 수 있습니다.

예들들어 자원 미 해제로 인해 finalizer가 지속적으로 수행되어 CPU 과부하가 발생한 경우입니다.


그럼 실제 Heap dump를 생성하는 방법에 대해 알아보겠습니다.

먼저 Sun Java에서 Heap dump를 생성하는 방법입니다.

Heap dump 생성 방법은 다음과 같습니다.

- HPROF 옵션과 함께 JVM 기동한 경우입니다.

- HeapDumpOnOutOfMemoryError 옵션과 함께 JVM 기동한 경우입니다.

- HeapDumpOnCtrlBreak 옵션과 함께 JVM 기동한 경우입니다.


a. HPROF 옵션과 함께 JVM을 기동한 경우는 다음과 같습니다.

HPROF JVM에서 제공하는 profiling 기능으로 JVMTI(Java Virtual Machine Tool Interface)를 사용하여 JVM interface하는 dynamically-linked library 입니다.

HPROF profiling 기능을 내재하고 있기 때문에 CPU 사용률, Java heap allocation 상태, monitor contention, thread 상태 등에 대한 정보를 제공합니다. 일반적으로 이러한 기능들을 제공하는 툴을 Java Profiler라고 합니다.

실제로 HPROFperformance, lock contention, memory leak 및 기타 다양한 문제를 분석하는데 효과적으로 활용됩니다.

HPROF를 설정 위해서는 java 명령어 옵션을 통해 가능합니다.(Java 1.5 이상 일 경우이며 이하 버전은 별도의 옵션이 필요합니다.)


HProf 의 기본적인 명령어는 다음과 같습니다.


java -Xrunhprof: heap=sites,cpu=samples,file=prof2.txt [Main Class] (>= JDK 1.4) 

java -agentlib:hprof= heap=sites,cpu=samples,file=prof2.txt [Main Class] (>= JDK 1.5)


HProf 의 실행 결과는 파일명을 따로 지정하지 않으면 java.hprof.txt 라는 이름으로 저장됩니다. 이 파일명은 file= 옵션으로 변경할 수 있습니다. 또한 다양한 옵션에 따라 다른 결과를 확인할 수 있으며, heap 옵션들은 아래와 같습니다.


heap옵션 : java의 heap에 대한 profiling을 수행하기 위한 것입니다. 이는 dump, site, all 3가지 값을 설정할 수 있습니다. 

- dump : 현재 heap의 모든 allocate된 object 에 대한 정보를 출력합니다. 

- sites : 현재 사용되고 있는 object들에 대한 점유 비율을 알 수 있습니다. 

- all : dump와 site의 모든 내용을 생성할 수 있습니다. 


b. HeapDumpOnOutOfMemoryError 옵션과 함께 JVM을 기동한 경우는 다음과 같습니다.

이 옵션은 Java 1.5 이상일 경우 사용 가능합니다.

JVM Java heap 메모리 또는 permanent 영역의 full로 인해 OutOfMemoryError가 발생할 경우 JVM heap dump를 생성하도록 하는 옵션입니다. 가장 유용한 옵션으로 언제 발생할지 모를 OutOfMemoryError를 대비해서 Heap dump를 생성하도록 하는 옵션입니다

 -XX:+HeapDumpOnOutOfMemoryError


메모리 문제로 인해 의도적으로 Heap dump를 남기는 경우(HPROF 또는 HeapDumpOnCtrlBreak)보다 안정적인 운영 상태에서 선택할 수 있는 옵션입니다.

이렇게 생성되는 Heap dump파일은 기본적으로 Java프로세스의 working 디렉토리에 java_pid<pid>.hprof 파일명으로 생성됩니다.

생성되는 Heap dump 파일의 위치를 지정하기 위해서는 -XX:HeapDumpPath 옵션을 통해 지정이 가능합니다.



c. HeapDumpOnCtrlBreak 옵션과 함께 JVM을 기동한 경우는 다음과 같습니다.

이 옵션은 위의 HeapDumpOnOutOfMemoryError와 동일하게 동작하여 Heap dump를 생성합니다.


 -XX:+HeapDumpOnCtrlBreak


, Heap dump가 생성되는 시점의 이벤트가 OutOfMemoryError가 아닌 Ctrl+Break 또는 SIGQUIT Signal에 의해 생성되는 것이 다릅니다. 생성되는 Heap dump파일명은 java_pid<pid>.hprof.<yyyymmdd>.<hhmmss> 파일명으로 생성됩니다. 이 옵션은 window에서는 적용되지 않습니다.


e. jmap 을 사용하여 heap dump를 생성하는 방법입니다. 

별도로 JVM 옵션에 명시할 필요없이 JDK에 포함되어 있는 jmap을 사용해 heap dump를 생성할 수 있습니다. Windows 버전은 JDK 1.5 버전에 jmap이 포함되어 있지 않으므로 사용할 수 없다. Heapdump를 수집하는 방법은 아래와 같습니다. 


 - jmap -heap:format=b <pid> (JDK 1.5)

 - jmap -dump:format=b,file=<filename> <pid> (JDK 6)



다음으로 HP Java에서 Heap dump를 생성하는 방법입니다.

Heap dump 생성 방법은 다음과 같습니다.

- HPROF 옵션과 함께 JVM 기동한 경우입니다.

- HeapDump 옵션과 함께 JVM 기동한 경우입니다.

- HeapDumpOnOutOfMemoryError 옵션과 함게 JVM 기동한 경우입니다.

- HeapDumpOnCtrlBreak 옵션과 함께 JVM 기동한 경우입니다.

- HeapDumpOnly 옵션과 함께 JVM 기동한 경우입니다.


a. HPROF 옵션과 함께 JVM을 기동한 경우는 다음과 같습니다.

Sun Java에서 설명한 HPROF 동작과 동일합니다.


b. HeapDump 옵션과 함께 JVM을 기동한 경우는 다음과 같습니다.

이 옵션은 Java 1.5이상일 경우 사용 가능한 옵션입니다. 또한 "_JAVA_HEAPDUMP"라는 shell 환경 변수 설정으로도 동일하게 동작합니다.

Heap dump를 생성하기 위해서는 Java 프로세스에 Ctrl+Break 또는 SIGQUIT Signal을 발생시켜 생성할 수 있습니다. Thread dump 생성과 동일한 방법입니다. 생성되는 Heap dump 파일은 ASCII 포맷입니다.


c. HeapDumpOnOutOfMemoryError 옵션과 함께 JVM을 기동한 경우는 다음과 같습니다.

이 옵션 또한 Java 1.5 이상일 경우 사용 가능한 옵션입니다. JVM Java heap 또는 permanent 영역의 full로 인해 OutOfMemoryError가 발생할 경우 JVM Heap dump 파일을 생성하도록 하는 옵션입니다.

이 옵션은 Sun HeapDumpOnOutOfMemoryError 옵션과 같은 기능을 제공합니다.


d. HeapDumpOnCtrlBreak 옵션과 함께 JVM을 기동한 경우는 다음과 같습니다.

이 옵션은 위의 HeapDumpOnOutOfMemory와 동일하게 동작하며 Heap dump를 생성합니다.

이 옵션 또한 Sun HeapDumpOnCtrlBreak 옵션과 같은 기능을 제공합니다.


e. HeapDumpOnly 옵션과 함게 JVM을 기동한 경우는 다음과 같습니다.

이 옵션 또한 Java 1.5 이상일 경우 사용 가능한 옵션입니다. 또한 "_JAVA_HEAPDUMP_ONLY" shell 환경변수 설정으로도 동일하게 동작합니다.

Java 프로세스의 SIGVTALRM Signal (signal 넘버 20)에 의해 생성되며, 생성되는 파일의 포맷은 ASCII입니다.


IBM Java에서 Heap dump를 생성하는 방법입니다.

Heap dump 생성 방법은 다음과 같습니다.

- HPROF 옵션과 함께 JVM 기동한 경우입니다.

- Dump agent 옵션과 함께 JVM 기동한 경우입니다.

- IBM_HEAPDUMP, IBM_HEAP_DUMP shell 환경변수와 함께 JVM 기동한 경우입니다.

- IBM_HEAPDUMP_OUTOFMEMORY shell 환경변수와 함께 JVM 기동한 경우입니다.

 

a. HPROF 옵션과 함께 JVM을 기동한 경우는 다음과 같습니다.

Sun Java에서 설명한 HPROF 동작과 동일합니다.


b. Dump agent 옵션과 함께 JVM을 기동한 경우는 다음과 같습니다.

Dump agent JVM에서 발생하는 각종 event (GC, thread start, JVM termination ) 에 따라 수행되는 기능을 정의할 수 있는 IBM JVM의 기능입니다.


c. IBM_HEAPDUMP, IBM_HEAP_DUMP shell 환경변수와 함께 JVM을 기동한 경우는 다음과 같습니다.

IBM_HEAPDUMP, IBM_HEAP_DUMP shell 환경변수를 TRUE로 설정한 상태에서 JVM을 기동한 경우 crash user signal을 통해 heap dump를 생성할 수 있습니다물론 이러한 shell 환경변수를 설정하게 되면 내부적으로 Dump agent heap dump 생성 옵션이 설정되는 것입니다. 이렇게 설정한 경우 heap dump를 생성하기 위해 Ctrl+Break 또는 SIGQUIT signal을 사용하게 됩니다. 이 경우 javacore 파일과 같이 생성되게 됩니다.

이렇게 생성된 heap dump 파일은 바이너리 포맷(PHD)으로 생성됩니다

또한 IBM_HEAPDUMPDIR shell 환경변수를 설정하여 heap dump파일이 생성되는 위치도 지정이 가능합니다.


d. IBM_HEAPDUMP_OUTOFMEMORY shell 환경변수와 함께 JVM을 기동한 경우는 다음과 같습니다.

IBM_HEAPDUMPOUTOFMEMORY shell 환경변수를 TRUE로 설정한 상태에서 JVM을 기동한 경우 OutOfMemoryError가 발생할 경우 heap dump가 생성됩니다. 이렇게 생성된 heap dump 파일은 바이너리 포맷(PHD)으로 생성됩니다.


마지막으로 Heap dump 내용을 실제로 분석해 보도록 하겠습니다.

먼저 Sun 계열에 HeapDump입니다.

Sun 계열의 Heap dump IBM 계열의 Heap dump와 다르게 HPROF를 통해 생성되어 내부에 다양한 정보(stack trace, object size, object value)를 포함하게 됩니다물론 IBM 계열도 HPROF 기능을 제공하지만 Heap dump 내용에는 object와 Java 소스파일 상관관계와 size등의 정보만을 포함합니다. 

각 시점의 TRACE 내용과 Heap dump의 시작과 ROOT 노드에 대한 내용이 포함되어 있습니다.

또한 object의 주소번지, size, 관련 TRACE 번호, Loaded Object정보와 object attributes(변수 등)에 대한 정보들도 포함되어 있습니다.

이러한 object 내의 attribute들에 대한 주소 값을 계속 찾아가다 보면 실제 저장되어 있는 값(value)도 알 수가 있습니다. 예를 들어 aaa라는 object attribute 중에 name 이라는 String 형의 attribute가 있다면 name object의 주소 값을 찾아가보면 name object 아래에 char[] 배열 object가 있으며 이 char[] 배열 객체 안에 실제 String의 문자열 값이 있습니다. 이렇게 Heap dump를 확인하게 되면 실제로 object들의 구성과 내부의 attribute등에 대한 자세한 정보들을 확인할 수 있습니다.


아래 내용은 Sun 계열의 Heapdump를 analyzer로 분석한 결과입니다. tool은 IBM Heap Analyzer를 사용하였습니다. 


- File > Open > 파일 선택 후 열기를 하면 분석이 진행됩니다. 

- Heap Dump Information에서는 Root의 수,Timestamp,Class수 등 summary를 확인할 수 있습니다. 



- Heap dump 분석결과에서 가장 중요한 부분이 Leak Suspect입니다. 

아래 결과에서는 37.99% 를 점유중인 object와 27.95% 를 점유중인 object에 대해 분석해볼 필요가 있습니다. 



- 추가적으로 Analysis Tab에서는 아래와 같은 다이어그램이 확인됩니다..



- 하단의 Reference Tree를 살펴보겠습니다. object에서 참조하고 있는 attribute들을 tree 구조로 확인 할 수 있습니다.

  아래는 37.99% 를 차지하고있는 object의 tree 구조를 살펴본 내용입니다. 

   org.objectweb.asm 관련한 attribute들이 반복적으로 확인되어, suspect로 확인이 됩니다. 



- 다음으로 27.95% 를 점유중인 object의 tree 구조를 살펴보겠습니다. 

   egovframework.rte.psl.dataaccess.util.EgoMap 에서 볼수있듯이 data를 수집하여 access하는 부분을 의심할 수 있습니다. 






다음으로 IBM 계열의 HeapDump입니다.

Heap dump의 시작과 시작 object에 대한 정보를 확인할 수 있습니다. 그리고 각 object들과 해당 object들의 하부 object들에 대한 주소 정보들을 확인할 수 있습니다. 그러나 Sun 계열에서의 object들에 대한 attribute 정보와 데이터에 대한 정보는 없는 것을 알 수 있습니다. 이러한 특징들로 인해 IBM 계열의 Heap dump가 문제 분석에 있어서 Sun 계열보다 분석할 수 있는 내용에 제약이 있을 수 밖에 없습니다.


Heap dump를 이용하여 object들 간의 관계는 다음과 같습니다.

Java에서는 각 object간의 관계가 reference(참조)를 통해 이루어 집니다. 따라서 각 object들의 attribute (attribute object)들 간에는 reference를 통해 모두 연결이 이루어 집니다. 이러한 reference들의 연결이 없는 객체(참조계수가 0)들은 GC(Garbage Collection)의 대상이 되어 JVM이 자동으로 해제하게 됩니다. object들의 reference들을 연결하게 되면 커다란 tree 구조가 만들어 집니다. 이렇게 만들어진 tree를 통해 어느 부분의 object들이 많은 메모리를 차지하고 있으며, OutOfMemoryError를 유발했는지를 확인하고 해당 어플리케이션을 유추해 나갈 수가 있습니다.


아래 내용은 IBM JAVA 계열의 Heapdump를 analyzer로 분석한 결과입니다. tool은 IBM Heap Analyzer를 사용하였습니다. 


- File > Open > 파일 선택 후 열기를 하면 분석이 진행됩니다. 


- Heap Dump Information에서는 Root의 수,Timestamp,Class수 등 summary를 확인할 수 있습니다. 



- Leak Suspect와 다이어그램을 보니, Hashtable관련 instance에서 82.53%의 Java Heap을 사용하고 있네요. 





- Reference Tree에서 해당 instance를 선택해 보겠습니다. 

  jeus.servlet.session2.UserSession 이라는 API에 대해 확인할 필요가 있습니다. 사용자의 session을 처리하는 과정에서 OutOfMemory가   발생했을 가능성도 있으며, thread dump와 병행하여 분석이 필요할 수 있습니다. 




HeapDump 분석은 위와 같이 실제 Memory를 사용하는 Application 또는 WAS의 상세 StackTrace 및 사용량을 확인할 수 있으며 내부 Attribute 까지 확인이 가능합니다.

이를 활용하여 메모리 사용량이 높은 Application을 튜닝하여 보다 효율적으로 관리 할 수 있어야 하겠습니다.

맙습니다.

728x90
반응형