Heap dump란?

Development/Java 2012. 2. 2. 05:34

안녕하세요. 이번에는 Heap dump 분석을 위해 Heap dump가 무엇인지에 대해 알아보도록 하겠습니다.
그럼 Heap dump란 무엇일까요? 
우선 Heap이란 Java에서 사용하는 object들을 저장하는 공간입니다. 물론 Heap이란 용어가 꼭 Java에서만 사용되는 용어는 아닙니다.
Unix에서 Native 즉 C에서 malloc()으로 할당되는 메모리 영역을 Heap(예전에 공부할때 자유저장소 라고도 했었죠 ^^)이라고 말합니다. 물론 Java에서 사용하는 Heap 메모리도 Native 영역의 프로세스 메모리에 생성됩니다.
Java에서 Heap은 Java가 관리하는 별도의 메모리 공간이라고 보면 될 것같습니다. 이후에서 말하는 Heap은 모두 Java Heap을 의미하도록 하겠습니다.
Heap에는 java object 정보만 저장되는 것이 아니고 class 메타 정보 및 각 object들에 대한 참조 정보도 담겨 있습니다.
Heap 메모리에 존재하는 모든 object는 Root 노드부터 시작해서 parent/child 형식의 tree 구조를 형성하고 있습니다. 
이러한 tree 구조는 각 object들의 참조 정보를 통해 이루어집니다. 
tree 구조가 꼭 정형화된 top/down 방식의 구조로만 이루어지지 않고 간혹 역참조에 의해 상호 참조가 발생하기도 합니다.
Heap의 정보를 분석하는 것은 java에서의 메모리 문제(각종 OutOfMemoryError 문제들)를 해결하기 위한 중요한 작업입니다. 
Java가 메모리 사용에 있어서 메모리 할당/해제에 대한 기능을 java가 자체적으로 지원(Garbage Collection)하여 다른 언어(C, C++등) 보다 개발의 편의성을 제공하지만 이에 따른 메모리에 대한 문제점을 항시 내포하고 있는 것이 사실입니다. 
이러한 문제점을 해결하기 위해서 Heap을 분석하는 것이 많은 도움을 줍니다.
각 Java 벤더별로 Heap dump를 생성하는 방법과 그 내용이 조금씩 다른데요. 
크게 IBM 계열과 Sun 계열로 나눌 수 있습니다. 
예를 들어 두 계열의 Heap dump의 가장 큰 차이점은 object에 대한 데이터를 포함하느냐 안하느냐의 차이가 있습니다. Sun 계열을 object에 대한 데이터들을 모두 담고 있으며, IBM 계열은 그렇지 않고 object들에 대한 참조 정보만 담겨 있습니다.

자, 그럼 이러한 Heap dump를 통해 분석할 수 있는 문제점에는 어떤것들이 있을까요 ?
첫번째로 OutOfMemoryError에 대한 문제를 분석하는 것입니다.
Heap dump로 할 수 있는 가장 중요하고도 기본적으로 해결할 수 있는 문제입니다.
두번재로 Permanent Full에 대한 문제 분석입니다.
loaded class의 메타정보들에 대한 정보를 분석하므로써 Permanent Full 문제에 대한 분석이 가능합니다.
물론 Permanent Full도 일종의 OutOfMemoryError라고 할 수 있습니다.
세번째로 메모리 Leak 문제 분석입니다.
메모리 Leak이 지속되면 OutOfMemoryError가 되지만 OutOfMemoryError가 발생하지 않고 많은 메모리를 점유하고 해제되지 않고 있어 GC의 빈도가 잦아져 문제가 발생되는 경우에 Heap dump를 통해 해제되지 않는 object들을 확인할 수 있습니다.
네번째로 기타 Heap과 관련된 문제 분석입니다.
복합적인 원인으로 문제가 발생할 경우 문제 분석을 위한 하나의 정보로서 Heap dump를 활용할 수 있습니다.
예들들어 자원 미해제로 인해 finalizer가 지속적으로 수행되어 CPU 과부하가 발생한 경우입니다.

위와 같은 문제에 대한 분석은 앞으로 차차 사례를 통해 분석 방법을 알아 보도록 하겠습니다.

이제 부터 Heap dump를 어떻게 생성하는지에 대해 Java 계열별로 설명드리도록 하겠습니다.

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

다음과 같은 방법으로 Heap dump를 생성할 수 있습니다.
- HPROF 옵션과 함께 JVM을 기동한 경우
- HeapDumpOnOutOfMemoryError 옵션과 함께 JVM을 기동한 경우
- HeapDumpOnCtrlBreak 옵션과 함께 JVM을 기동한 경우
- jmap 명령어를 통한 Heap dump 생성

그럼 위의 경우에 대해 하나씩 알아 보도록 하겠습니다.

- 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라고 합니다.
실제로 HPROF는 performance, lock contention, memory leak 및 기타 다양한 문제를 분석하는데 효과적으로 활용됩니다. HPROF를 통한 어플리케이션 profiling은 다음 포스트(http://blog.naver.com/bumsukoh/110119532123)를 참고하세요.
HPROF를 설정 위해서는 다음과 같이 java 명령어 옵션을 통해 가능합니다.(Java 1.5 이상 일 경우이며 이하 버전은 별도의 옵션이 필요합니다.)


다음은 HPROF 옵션을 위한 help 부분입니다.


실제 HPROF를 통한 Heap dump 생성 예제는 다음과 같습니다.


- HeapDumpOnOutOfMemoryError 옵션과 함께 JVM을 기동한 경우
이 옵션은 Java 1.5 이상일 경우 사용 가능합니다.
JVM이 Java heap 메모리 또는 permanent 영역의 full로 인해 OutOfMemoryError가 발생할 경우 JVM이 heap dump를 생성하도록 하는 옵션입니다.
이 옵션이 가장 유용한 옵션으로 언제 발생할지 모를 OutOfMemoryError를 대비해서 Heap dump를 생성하도록 하는 옵션입니다. 
이 경우 메모리 문제로 인해 의도적으로 Heap dump를 남기는 경우(HPROF 또는 HeapDumpOnCtrlBreak등)보다 안정적인 운영 상태에서 선택할 수 있는 옵션입니다.
이렇게 생성되는 Heap dump파일은 기본적으로 Java프로세스의 working 디렉토리에 java_pid<pid>.hprof 파일명으로 생성됩니다. (pid는 프로세스 ID임)
생성되는 Heap dump 파일의 위치를 지정하기 위해서는 -XX:HeapDumpPath 옵션을 통해 지정이 가능합니다.
다음은 HeapDumpOnOutOfMemoryError 옵션을 적용한 Java 프로세스 기동 방법입니다.


- HeapDumpOnCtrlBreak 옵션과 함께 JVM을 기동한 경우
이 옵션은 위의 HeapDumpOnOutOfMemoryError와 동일하게 동작하여 Heap dump를 생성합니다.
단, Heap dump가 생성되는 시점의 이벤트가 OutOfMemoryError가 아닌 Ctrl+Break 또는 SIGQUIT Signal에 의해 생성되는 것이 다릅니다.
생성되는 Heap dump파일명은 java_pid<pid>.hprof.<yyyymmdd>.<hhmmss> 파일명으로 생성됩니다.
이 옵션은 window에서는 적용되지 않습니다.
다음은 HeapDumpOnCtrlBreak 옵션을 적용한 Java 프로세스 기동 방법입니다.


다음으로 HP Java에서 Heap dump를 생성하는 방법에 대해 설명드리겠습니다.

HP Java에서는 다음과 같은 방법으로 Heap dump를 생성할 수 있습니다.

- HPROF 옵션과 함께 JVM을 기동한 경우
- HeapDump 옵션과 함께 JVM을 기동한 경우
- HeapDumpOnOutOfMemoryError 옵션과 함게 JVM을 기동한 경우
- HeapDumpOnCtrlBreak 옵션과 함께 JVM을 기동한 경우
- HeapDumpOnly 옵션과 함께 JVM을 기동한 경우

그럼 위의 경우에 대해 하나씩 알아 보도록 하겠습니다.

- HPROF 옵션과 함께 JVM을 기동한 경우
Sun Java에서 설명한 HPROF 동작과 동일합니다. 위의 내용을 참고하시기 바랍니다.

- HeapDump 옵션과 함께 JVM을 기동한 경우
이 옵션은 Java 1.5이상일 경우 사용가능한 옵션입니다. 또한 "_JAVA_HEAPDUMP"라는 shell 환경 변수 설정으로도 동일하게 동작합니다. (예, export _JAVA_HEAPDUMP=1)
Heap dump를 생성하기 위해서는 Java 프로세스에 Ctrl+Break 또는 SIGQUIT Signal을 발생시켜 생성할 수 있습니다. 즉 Thread dump 생성과 동일한 방법입니다.
생성되는 Heap dump 파일은 ASCII 포맷이며, 파일명은 java_<pid>_<time>_heapDump.hprof.txt 형식으로 생성됩니다.
다음은 HeapDump 옵션을 적용한 Java 프로세스 기동 방법입니다.


- HeapDumpOnOutOfMemoryError 옵션과 함께 JVM을 기동한 경우
이 옵션 또한 Java 1.5 이상일 경우 사용가능한 옵션입니다. 
JVM이 Java heap 또는 permanent 영역의 full로 인해 OutOfMemoryError가 발생할 경우 JVM이 Heap dump 파일을 생성하도록 하는 옵션입니다.
이 옵션은 Sun의 HeapDumpOnOutOfMemoryError 옵션과 같은 기능을 제공합니다.(Sun Java HeapDumpOnOutOfMemoryError 참조)

다음은 HeapDumpOnOutOfMemoryError 옵션을 적용한 Java 프로세스 기동 방법입니다.


- HeapDumpOnCtrlBreak 옵션과 함께 JVM을 기동한 경
이 옵션은 위의 HeapDumpOnOutOfMemory와 동일하게 동작하며 Heap dump를 생성합니다.
이 옵션 또한 Sun의 HeapDumpOnCtrlBreak 옵션과 같은 기능을 제공합니다.(Sun Java HeapDumpOnCtrlBreak 참조)
다음은 HeapDumpOnCtrlBreak 옵션을 적용한 Java 프로세스 기동 방법입니다.


- HeapDumpOnly 옵션과 함게 JVM을 기동한 경우
이 옵션 또한 Java 1.5 이상일 경우 사용가능한 옵션입니다.
또한 "_JAVA_HEAPDUMP_ONLY" shell 환경변수 설정으로도 동일하게 동작합니다. (예, export _JAVA_HEAPDUMP_ONLY=1)
Java 프로세스의 SIGVTALRM Signal (signal 넘버 20)에 의해 생성되며, 생성되는 파일의 포맷을 ASCII입니다.
생성되는 파일명은 java_<pid>_<date>_<time>_heapDump.hprof.txt 형식으로 생성됩니다.
다음은 HeapDumpOnly 옵션을 적용한 Java 프로세스 기동 방법입니다.


다음으로 IBM Java에서 Heap dump를 생성하는 방법에 대해 설명드리겠습니다.
IBM Java에서는 다음과 같은 방법으로 Heap dump를 생성할 수 있습니다.
- HPROF 옵션과 함께 JVM을 기동한 경우
- Dump agent 옵션과 함께 JVM을 기동한 경우
- IBM_HEAPDUMP, IBM_HEAP_DUMP shell 환경변수와 함께 JVM을 기동한 경우
- IBM_HEAPDUMP_OUTOFMEMORY shell 환경변수와 함께 JVM을 기동한 경우

자! 그럼 이번에도 위의 경우에 대해 하나씩 알아 보도록 하겠습니다.

- HPROF 옵션과 함께 JVM을 기동한 경우
Sun Java에서 설명한 HPROF 동작과 동일합니다. 위의 내용을 참고하시기 바랍니다.

- Dump agent 옵션과 함께 JVM을 기동한 경우
Dump agent는 JVM에서 발생하는 각종 event (GC, thread start, JVM termination 등) 에 따라 수행되는 기능을 정의할 수 있는 IBM JVM의 기능입니다.
다음은 Dump agent의 종류와 event에 대한 내용입니다. (Dump agent에 대한 자세한 사항은 "IBM Diagnostic" 포스트 내용을 참조하시기 바랍니다.)

Dump agent 종류 확인을 위한 java -Xdump:help 명령 수행 결과입니다.


Dump agent가 지원하는 event 종류를 확인하기 위한 java -Xdump:events 명령 수행 결과입니다.

이러한 Dump agent를 통해 Heap dump를 생성하는 방법과 생성 결과는 다음과 같습니다.




위와 같이 "-Xdump:none" 옵션을 설정하여 전체 dump 옵션을 모두 ignore 시킵니다.
그리고 "-Xdump:heap:events=vmstop,opts=PHD+CLASSIC" 옵션을 통해 heap dump를 생성하는데, vmstop(JVM이 down될 경우) event가 발생할 경우 PHD 포맷과 CLASSIC 포맷(TEXT 포맷)으로 heap dump를 생성하게 됩니다.

- 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파일이 생성되는 위치도 지정이 가능합니다.
생성된 heap dump 파일의 파일명은 heapdump.<YYYYMMDD>.<HHMISS>.<pid>.<순번>.phd 로 생성됩니다.

다음은 shell 환경 변수 설정 예입니다.


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

다음은 shell 환경 변수 설정 예입니다.


지금까지 Heap dump란 무엇이며, Sun/HP/IBM Java에서 Heap dump를 생성하는 방법에 대해 알아 보았습니다.
다음 시간에는 Heap dump에 무슨 내용이 어떻게 들어 있는지 알아보도록 하겠습니다.
그럼 즐거운 시간되세요. ^

출처 -  http://blog.naver.com/bumsukoh?Redirect=Log&logNo=110123438564&from=postView 


Posted by linuxism
,