본문 바로가기
Stackoverflow

heap dump -출처:http://kwonnam.pe.kr/wiki/java/memory

by forkballpitch 2017. 9. 25.
728x90
728x90

heap dump란


 

이번 포스트에서는 메모리 Leak 문제를 Heap dump를 통해 분석하는 방법에 대해 사례를 통해 알아 보도록 하겠습니다.

메모리 Leak이 발생하는 Java 프로세스의 최종 종착점은 OutOfMemoryError일 것이며, 이는 Java 프로세스가 down 되거나 지속적인 Garbage Collection이 수행되어 성능상의 문제를 일으키게 됩니다.

이러한 메모리 Leak을 감지하기 위해서는 메모리 사용율을 지속적으로 모니터링 해야하며, 모니터링을 해야할 주요한 데이터로는 GC Log가 있습니다.

메모리 모니터링을 통해 메모리 Leak이 발생하고 있다는 것이 감지되면 Heap dump를 생성하여 메모리 Leak이 발생하는 원인을 분석하고 조치를 취해야 되겠죠.


그럼 이러한 메모리 Leak 문제를 분석하는 방법에 대해 사례를 통해 알아보도록 하겠습니다.

우선 이해도를 높이기 위해 사례 case의 AP 구조를 먼저 살펴보도록 하겠습니다.



이번 사례는 위의 그림과 같이 웹어플리케이션에서 사용하는 세션 정보에 지속적으로 객체가 등록됨으로써 가용 메모리가 차차 줄어드는 경우입니다.


그럼 메모리 Leak을 확인하는 가장 좋은 방법 인 GC Log를 분석한 내용을 살펴 보도록 하겠습니다.



위의 그림과 같이 메모리의 Used가 GC가 수행되어도 지속적으로 증가하는 경우는 Leak으로 의심해 볼 수 있는 경우라 할 수 있습니다.

일반적인 경우는 메모리가 지속적으로 증가하다 전체 메모리의 한계에 도달하게 되면 GC에 의해 메모리가 줄어들게 되는데 이 시점에 Full GC가 발생하게 되고 수행 시간이 오래 걸려 성능상에 문제가 발생하게 됩니다.

물론 이러한 경우도 AP 튜닝 또는 Java 메모리 옵션 변경을 통해 성능을 개선할 수 있습니다.

그러나 위의 경우는 전체 메모리의 한계에 도달하여 GC에 의해 메모리를 정리하였음에도 불구하고 메모리의 사용율이 낮아지지 않고 메모리량이 유지되면서 빈번한 Full GC를 유발하는 경우입니다. 물론 조금 지나면 OutOfMemoryError가 발생하게 되겠죠.


이러한 상태에서 Heap dump를 생성하여 HeapAnalzer를 통해 분석해 보도록 하겠습니다.

우선 이러한 경우 Heap dump를 생성하기 위해서는 메모리 Leak인 상태에 Heap dump를 생성할 수 있는 옵션이 용이합니다. Ctrl-Break를 통한 Heap dump 생성 옵션이 가장 유용하게 사용됩니다.



위의 그림과 같이 HeapAnalyzer를 통해 Heap dump를 오픈하여 Leak suspect 부분을 확인합니다.

그리고 Leak suspect 부분을 클릭하여 reference tree상에서 해당 부분을 확인합니다.



위의 그림과 같이 해당 부분을 살펴보면 Hashtable 객체의 parent가 WAS의 session 저장 객체인것을 알 수 있습니다.

Hashtable 하부에 다시 Hashtable 객체가 2000개 이상 들어 있는 것을 알 수 있습니다.


그럼 Hashtable 내의 객체에 대해 좀 더 상세히 알아보도록 하겠습니다.



위와 같이 Hashtable 객체내에 Session 저장 객체인 DataSetImpl이라는 객체가 존재하는 것을 알 수 있습니다.

DataSetImpl 하부로 Vector와 String등의 객체들이 존재하는 데요.

Hashtable의 key인 String 객체의 데이터를 보기 위해 property의 내용을 확인합니다.

이전 포스트에서도 설명드렸듯이 Sun 계열의 Heap dump는 해당 객체의 attribute들과 저장 데이터에 대한 내용을 포함하고 있어 확인이 가능합니다. 그러나 안타깝게도 IBM 계열은 이러한 데이터를 포함하고 있지 않습니다.

property의 내용을 보니 "DATASET63" 이라는 key를 가지고 있는 Hashtable임을 알 수 있습니다.

그리고 DataSetImpl 객체는 Vector 객체 2개와 String 객체 하나로 이루어져 있는 것을 알 수 있는데요. 이 중 String 객체의 데이터를 확인해 보면 SQL문인 것을 알 수 있습니다.

이렇게 여기까지 분석으로도 충분히 DataSetImpl이라는 객체가 Session 내에 저장되어 있는 것을 확인 할 수 있으며, 이러한 DataSetImpl 객체는 DB 처리 결과 데이터를 담고 있는 객체로 SQL문을 수행한 결과 정보가 Session에 저장되어 있는 것을 보아 특별한 목적을 위해 사용하거나 아니면 잘못된 구조 설계로 빚어진 결과일 것입니다.

그럼 여기서 DataSetImpl 객체의 갯수와 내역을 확인하기 위해 Type View를 수행하여 보도록 하겠습니다.



위와 같이 Type list로 확인했을 때 DataSetImpl 객체가 총 3548개가 존재하는 것을 알 수 있으며, 마우스 right click을 해서 "Find same type"으로 확인했을때 class 하나에 다른 객체들이 무수히 있는 것을 확인할 수 있습니다.

많은 객체들이 생성되어 해제되지 않고 존재하는 것을 확인할 수 있습니다.


그럼 여기서 좀더 상세하고 분석효과를 높이기 위해 reference tree를 통해 객체들의 구조에 대한 개념도를 그릴수 있는데요. 이러한 개념도는 복잡한 구조의 객체 관계가 있는 Heap dump를 분석하는데 굉장히 유용하게 쓰입니다.

그렇다면 DataSetImpl 객체의 구조를 reference tree를 통해 그려 보도록 하겠습니다.



위와 같이 DataSetImpl은 하부에 Vector 객체 둘과 String 객체 하나로 이루어져 있으며, String 객체에는 수행한 SQL에 대한 정보가 들어 있습니다.

그리고 첫번째 Vector에는 다시 하부에 Vector를 가지고 있으며, 그 Vector 내부에는 String 객체가 포함되어 있습니다.

그리고 두번째 Vector에는 하부에 String 객체를 포함하고 있습니다.

각 String들의 내용을 확인해 보면 첫번째 Vector에는 SQL문을 수행한 결과가 저장되어 있으며, 두번째 Vector에는 SQL문의 결과 colume 정보가 포함되어 있습니다.

즉, DB에서 처리한 결과에 대한 정보가 포함되어 있는 데이터 객체로 짐작할 수 있습니다.


이번 사례에서는 사용자 세션에 DB에서 조회한 결과를 저장함으로써 메모리 Leak이 발생한 경우입니다.

이러한 문제는 분석하기가 쉽지만 잘못된 프로그램 구조로 인해 종종 발생할 수 있는 사례가 되겠습니다.

여기서 중요한 점은 메모리 Leak을 분석하기 위한 절차로 "메모리 사용율 모니터링 -> 메모리 사용 패턴 확인 -> 메모리 Leak 여부 판단 -> 적당한 Heap dump 옵션 설정 -> 메모리 모니터링과 함께 Heap dump 생성 -> Heap dump 분석 -> 메모리 Leak 원인 조치" 이루어 집니다. 이중에서 메모리 사용율 모니터링은 메모리의 문제를 인식하기 위한 가장 중요한 부분입니다.

요즘은 APM 툴들을 통해서도 어느 object들에 대한 allocation 정보를 모니터링이 가능하므로 손쉽게 확인이 가능합니다. 물론 Heap dump를 분석하는 것만큼 상세하지는 않겠지만요.


이것으로 Heap dump를 통한 메모리 Leak 문제 분석에 대해 알아 보았습니다.

다음에는 "Heap dump를 통해 문제 분석 사례"의 마지막으로 "기타 연관된 문제 분석" 부분에 대해 설명드리도록 하겠습니다.

드뎌 겨울이 온 것 같습니다. 한동안 업무에 바빠서 오랜만에 포스트를 쓰게 되네요. 즐겁고 추억에 남을 겨울들 보내시기 바랍니다. ^^

그럼 이만 마치겠습니다


1.heap이란


우선 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에 무슨 내용이 어떻게 들어 있는지 알아보도록 하겠습니다.
그럼 즐거운 시간되세요. ^^

Java Memory Analysis

64Bit 운영체제에서 포인터 크기

  • 64Bit 운영체제에서라도 64bit long이 아니라 기본적으로 32bit 포인터를 사용한다.
  • 그러나 Heap 사이즈가 대략 32GB가 넘어가면 그때부터 64bit 포인터로 바뀐다. 이렇게 되면 포인터 자체가 차지하는 메모리가 너무 커서 낭비적이 될 수 있다.
  • 일반적으로 Heap Size가 31GB 정도일 때 32bit 압축 포인터가 거의 확실하게 사용된다. 그 이상일 때는 운영체제 환경, JDK 종류/버전 등에 따라 64bit가 사용될 가능성도 있다.
  • Oracle(SUN) JVM Options에서 UseCompressedOops=true 일 때 참조.

Heap Dump on OutOfMemoryError

  • Java 시작시에 다음과 같은 옵션을 주면, OutOfMemoryError로 인한 JVM에 종료시 Heap Dump를 생성해준다.
    -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=jvm.hprof
  • -XX:HeapDumpPath를 생략하면 JVM 시작 디렉토리에 java_pid<pid>.hprof형태로 생성된다.
  • -XX:+PrintClassHistogramAfterFullGC-XX:+PrintClassHistogramBeforeFullGC 등의 옵션으로 Full GC 전/후의 메모리 상태를 간략히 덤프할 수 있다. Java Garbage Collection 참조.

jmap

  • 힙 덤프(Heap Dump)를 뜬다.
  • WebServer - Heap Dump를 뜨는 작업은 매우 큰 용량과 시간을 필요로 하기 때문에 WebServer - WAS 구조일 때 WebServer를 내려서 WAS에 요청이 오지 않게 만든 뒤에 작업해야 한다.
  • live 옵션을 주면 live 객체만 덤프를 받는다. 이 옵션이 없으면 Heap 상의 모든 객체를 덤프 받는다.
  • 바이너리 파일로 덤프 받기
    # jmap 사용
    jps # Java PID 확인
    jmap -dump:live,format=b,file=파일명.bin <PID>
     
    # jmap 잘 안될때 force. live 허용 안됨.
    jmap -F -dump:format=b,file=파일명.bin <PID>
     
    # gcore 사용
    gcore -o 파일명.core <PID> # 파일명.core.<PID> 파일생성
    jmap -dump:format=b,file=파일명.bin /usr/java/defaults/bin/java 파일명.core
  • 한번에 확인해보기
    jps -v | grep "원하는검색어" | awk '{print $1}' | xargs jmap -dump:live,format=b,file=jdump.hprof
  • jstatd를 띄웠을 경우, <PID> 대신 <PID>@호스트네임:포트 형태로 호출해도 된다.
  • JVM 현재 메모리 상태 Foot print. 현재 메모리상의 클래스의 객체 갯수와 용량표시
    jmap -histo:live <PID>

jhat

  • 힙 덤프를 분석한다.
  • jhap -J-mx2048m 파일명.bin 실행후 http://localhost:7000/ 에서 살펴볼 수 있다.
    • 힘 덤프 파일의 크기가 클 경우 OOM 에러가 발생할 수 있으므로 -J-mx2048m 지정
  • 메모리를 너무 많이 먹어서 실제로 제대로 실행하기 힘듬.

MAT

용어

  • Shallow heap : 하나의 객체가 소비하는 메모리 용량. 객체 레퍼런스는 하나당 아키텍처에 따라 32bits(혹은 62bits)를 차지한다.
  • Ratained heap : 해당 객체의 모든 인스턴스를 GC했을 때 확보할 수 있는 메모리 총량.

IBM HeapAnalyzer

  • 힙덤프 파일의 크기가 크기 때문에 실행시 -Xmx2048m 형태로 메모리 옵션을 줘야 한다.

HPJmeter

  • GC Log, Heapdump 등을 분석할 수 있다.

jstat

현재 JVM의 메모리 상태를 확인해 볼 수 있다.

옵션명내용
class클래스 로더의 동작에 관한 통계 데이터
compilerHotSpot Just-in-Time 컴파일러의 동작에 관한 통계 데이터
gcGC된 heap의 동작에 관한 통계 데이터
gccapactiy세대마다의 용량과 대응하는 영역에 관한 통계 데이터
gccauseGC 통계 데이터의 개요(-gcutil 와 같다)와 직전 및 현재 (적용 가능한 경우)의 GC이벤트의 원인
gcnewNew 세대의 동작에 관한 통계 데이터
gcnewcapacityNew 세대의 사이즈와 대응하는 영역에 관한 통계 데이터
gcoldOld 세대 및 Permanent 세대의 동작에 관한 통계 데이터
gcoldcapacityOld 세대의 사이즈에 관한 통계 데이터
gcpermcapacityPermanent 세대의 사이즈에 관한 통계 데이터
gcutilGC 통계 데이터의 개요
printcompilationHotSpot 컴파일 방법의 통계 데이터

SSH로 특정 서버의 GC 상태보기

서버가 여러대일 경우 특정 서버에 자동 접속하여 해당 서버의 Tomcat 인스턴스를 찾아서 gcutil 실행

ssh myhostname 'bash -s' <<'ENDSSH'
jstat -gcutil `jps | grep Bootstrap | awk '{print $1}'` 1s
ENDSSH


728x90
728x90

'Stackoverflow' 카테고리의 다른 글

insertion sort  (0) 2017.09.26
통합 테스트를 실행할 때 데이터베이스를 깨끗하게 유지하는 방법?  (0) 2017.09.26
IE DUMP 뜨기  (0) 2017.09.25
IE 응답없음  (0) 2017.09.25
nosql특징  (0) 2017.07.21