블로그 이미지
잡초 개발자의 좌충우돌 이야기 yysvip

카테고리

분류 전체보기 (211)
Java Programing (24)
Web Programing (20)
Database (36)
Tool (46)
까칠한 IT (27)
까칠한 정보 (42)
까칠한 Strory (16)
까칠한 Project (0)
Total880,802
Today2,675
Yesterday6,898

달력

« » 2018.10
  1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30 31      

공지사항

Thread dump의 내용은 ? (IBM 계열)

  까칠한 남자 Strory       yysvip.tistory.com       잡초 개발자 까찰한 쑤의 좌충우돌 개발 이야기

 

이번에는 지난 시간에 이어 IBM 계열의 Java Thread dump의 구조와 무슨 내용이 들어 있는지에 대해 알아 보겠습니다.

 

Sun 계열의 경우 Thread dump 수행 시점의 간단한 Thread들의 정보와 Stack trace 정도만 제공해 주지만, IBM의 Thread dump는 수행 지점의 JVM 프로세스에 대한 매우 상세한 정보를 제공합니다.


이러한 이유에서 인지는 모르겠지만, IBM에서 Thread dump는 javadump 또는 javacore라고 불립니다. (이하 javacore라 칭함)


이 javacore는 Sun계열 처럼 STDOUT으로 출력되는 것이 아니라 별고의 파일로 생성됩니다.

또한 생성되는 파일의 위치도 지정할 수 있는 기능을 제공합니다.

 

그러면 javacore 파일은 어디에 생성되는 걸까요 ?
javacore의 생성 위치는 다음과 같은 우선순위 원칙에 따라 생성됩니다.


첫번째, IBM_JAVACOREDIR 환경 변수 설정 디렉토리
두번째, JVM 프로세스의 현재 Working directory
세번째, TMPDIR 환경 변수가 설정된 디렉토리
네번째, /tmp 디렉토리


각 단계별로 설정값이 없거나 javacore 파일 생성이 불가한 경우 차순위 단계의 디렉토리에 생성되게 됩니다.

 

그럼 이제 javacore 파일명은 포맷에 대해 알아 보겠습니다.
기본 파일 명은 "javacore.%Y%m%d.%H%M%S.%pid.txt" 입니다.
- 파일명 예 : javacore.20110818.010122.12345.txt


이러한 파일명은 IBM Java dump agent의 설정을 통해 변경할 수 있습니다.
IBM java dump agent는 IBM JVM에서 사용하는 각종 Dump data 생성을 위한 설정을 제어 하기 위한 기능입니다.
여기서 말하는 각종 Dump data는 javacore, core dmp파일, heap dump 파일, trace buffer snap 파일등을 말합니다.


그림 IBM java agent 기본 설정 정보 확인 그림

 

IBM java dump agent는 내용이 많은 관계로 다음에 따로 포스팅하도록 하겠습니다.

 

여기까지 javacore 파일의 생성 디렉토리와 파일명에 대한 내용입니다.

문제가 발생하여 javacore를 생성하였지만 어느곳에 생성되는지 알 수 없어 찾지 못하는 경우가 생기곤 합니다.

이럴때 생성되는 디렉토리의 규칙과 파일명을 알면 쉽게 확인이 가능하게죠.

 

이제 javacore 파일의 내용에 대해 설명드리도록 하겠습니다.
IBM javacore는 만물상자다 !


위와 같이 말한 이유는 javacore 파일에는 생성되는 시점의 IBM JVM에 대한 거의 모든 정보가 담겨 있다고 할 수 있습니다.


이러한 javacore 파일의 내용을 이해하기 위해서는 IBM JVM 내부의 building block인 subcomponent에 대한 이해가 필요합니다.


다음은 IBM JVM의 subcomponent structure 입니다.

 

 
 

위 그림은 1.4버전의 Diagnostic 문서에 나오는 부분입니다. 1.5, 1.6의 문서에서는 해당 그림이 없어 졌더군요. 하지만 javacore 파일에는 해당 subcomponent 부분들로 나누어 정보가 기록되어 지고 있습니다.


각 부분에 대한 내용은 다음과 같습니다.
- CI(Core Interface) : User, 외부 프로그램, 환경에 관련된 인터페이스를 담당합니다.
- XM(Execution Management) : 다중 수행 엔진(Multiple execution engine)의 관리와  프로세스 control 기능을 제공합니다.
- DG(Diagnostics) : 각종 진단 기능과 서비스 디버그 기능 그리고 도구들을 제공합니다.
- XE(Execution Engine) : Byte code를 수행하기 위한 다양한 방법을 제공합니다.
- CL(Class Loader) : Java class들의 위한 모든 지원 기능들을 제공합니다.
- DC(Data Conversion) : 다양한 format들간의 data 변경 기능들을 제공합니다.
- LK(Lock) : Locking과 Synchronization 서비스 기능들을 제공합니다.
- ST(Storage) : Storage 서비스(메모리) 부분에 대한 기능들을 제공합니다.
- HPI(Hardware Platform Interface) : Low-level facility와 다양한 platform에 대한 서비스에 대한 기능들을 제공합니다.

 

위에서 언급한 각종 subcomponent에 대한 정보가 javacore 파일에 고스란히 들어 있습니다.

 

자, 그럼 javacore 파일의 간단한 예를 통해 javacore 파일의 구조를 설명하도록 하겠습니다.

 

 

 

위의 그림과 같이 javacore 파일의 각 라인 앞에는 Tag가 모드 붙어 있습니다.

각 Tag를 통해 해당 내용이 어느 부분인지(subcomponent 포함) 쉽게 알 수 있습니다.

 

다음은 Tag의 구조에 대한 설명입니다.


- 최대 15자리의 문자로 구성되어 있습니다.
- 첫번째 숫자는 각 구성요소의 순번을 의미합니다.
- 2~3번째 문자는 Section 정보를 의미합니다. (JVM subcomponent에 대한 정보임)
   - CI : Command-line interpreter
   - CL : Class loader
   - LK : Locking
   - ST : Storage(Memory Management)
   - TI : Title
   - XE : Execution Engine
   - XM : Execution Management
- 나머지는 출력라인에 대한 정보 문자입니다.
- 0SECTION Tag는 모든 Section의 시작을 의미합니다.

- NULL은 공백 라인에 대한 Tag 입니다.

 

이제 각 Section 별 샘플 내용을 살펴보도록 하겠습니다.

 


위의 그림은 TI 부분입니다. javacore에 대한 전체적인 정보가 담겨 있습니다.

위의 경우는 OutOfMemoryError에 의한 Dump Event가 발생하여 javacore가 생성된 경우인 것을 알 수 있습니다.

 

 


위의 그림은 XH 부분입니다. 해당 시스템(Host)에 대한 정보가 담겨 있습니다.

위에서는 CPU core수와 Chip Architecture 등이 보입니다.

 

 

 

위의 그림은 CI 부분입니다. 해당 Java 프로세스에 대한 Command 라인에 대한 정보가 담겨 있습니다.

Java 버전 및 수행 Command 등의 정보가 제공됩니다.

 

 

 

위의 그림은 ST 부분입니다. Java 메모리에 대한 정보가 담겨 있습니다.

위에서는 Heap space의 free와 allocated 정보 그리고 Internal, Object, Class의 메모리 segment에 대한 주소 정보등이 출력됩니다.

 

또한 일부 GC(Garbage Collector)에 대한 History 정보가 출력됩니다.

 

Heap free와 allocation의 byte 정보는 16진수 정보입니다. 따라서 680byte 를 10진수로 1664byte가 free 공간입니다.

OutOfMemoryError이 발생할 만한 상황인 것 같습니다.

 

 


위의 그림은 LK 부분입니다. Java 내부의 lock 정보가 담겨 있습니다.

 

이러한 lock 정보는 동기화 로직에 의해 Thread들이 대기상태에 빠진 경우 해당 Thread들이 어느 object나 Thread에서 lock 대기가 발생하였는지 확인 할 수 있는 정보를 출력합니다.

 

해당 Java 프로세스에서 사용하는 Lock Monitor에 대한 모든 정보가 출력됩니다.

 

 

... 중략

 

 

위의 그림은  XM, XE 부분입니다. Java의 Thread 정보와 Execute Engine(Thread stack trace)에 대한 정보를 담고 있습니다.

 

Java에 대한 callstack과 Native에 대한 callstack 모두 출력됩니다. 이렇게 Java와 Native가 같이 출력되는 것은 1.6 버전에서 가능합니다.

 

1.4, 1.5의 경우는 Java callstack만 출력됩니다.

 


...

 

 


위의 그림은 CL 부분입니다. Java 프로세스에서 사용되고 있는 모든 class loader와 class에 대한 정보가 담겨 있습니다.
각 ClassLoader와 ClassLoader가 load한 class에 대한 정보들이 출력됩니다.

잘못된 ClassLoader의 구현으로 동일한 class들이 중복적으로 생성될 경우는 CL 부분에서 ClassLoader의 중복과 Class의 중복 여부를 확인할 수 있습니다.

그러나 워낙 많은 정보가 출력되므로 찾는 것이 쉽지는 않다는 단점이 있습니다. ㅠ.ㅠ

 

다음으로는 javacore에서 분석 시 가장 많이 활용되는 Thread stack trace 정보 확인을 살펴보겠습니다.
javacore에서 Thread stack trace 정보는 XM, XE에 대한 정보가 출력되는 THREADS section에 담겨 있습니다.

 

다음은 THREADS section 과 Thread stack trace 부분 입니다.

위에서 설명드렸던 XM, XE의 부분의 샘플을 이용하여 상세히 설명하도록 하겠습니다.

 

 


... 중략

 


 

0SECTION Tag로 section의 시작을 확인할 수 있습니다. 그리고 그 밑에 XE 부분으로 해당 Thread에 대한 정보가 출력됩니다.

위에서는 Thread 명이 "Thread-46" 이며 상태가 "R(Runnable)" 입니다.
3XMTHREADINFO Tag로 해당 Thread에 대한 정보가 출력됩니다.
그리고 그 뒤로 Java stack이 이어지고, 그 다음으로 Native callstack이 나옵니다.
위에서 섦여드렸듯이 1.6 이전 버전에서는 Native callstack은 나오지 않습니다.

해당 Thread의 정보에는 Thread name, identifier, JVM data structure address, current state, java priority 정보가 출력됩니다.
이 중 Thread 상태 코드에 대한 내용은 다음과 같습니다.

 

- R : Runnable : Thread가 수행 가능한 상태(Run queue 진입)
- CW : Condition Wait : Thread가 wait 상태(sleep, I/O block, lock에 대한 wait등)
- S : Suspended : Thread가 다른 Thread에 의해 중지된 상태
- Z : Zombie : Thread가 kill 된 상태
- P : Parked : Concurrency API(java.util.concurrent)에 의해 park된 상태
- B : Blocked : Thread가 동기화 모듈을 통해 lock을 획득하기 위해 대기중인 상태

 

그럼 위의 예제를 통해 현재의 Thread의 상황에 대해 설명하도록 하겠습니다.

우선 위의 "Thread-46" Thread는 "R" 로써 Runnable 상태입니다.

 

그리고 Java stack trace를 봤을때 OutOrMemoryError 에러를 받아 Error를 Throw하고 있는 것을 알 수 있습니다.

이 Thread의 첫번째 stack은 LiveCheckManager.run()입니다. LiveCheckManager라는 Thread가 OutOfMemoryError를 발생시킨 것으로 볼수도 있으나 여기에는 함정이 있을 수 있습니다.

 

해당 Thread가 많은 메모리를 할당하려고 하여 발생한 것인지 아니면 이미 다른 Thread에서 메모리 leak으로 인해 메모리를 과점유 한 상태에서 LiveCheckManager Thread가 위에서 설명했던 free 메모리량인 1664byte 보다 많은 메모리를 allocation하려다 OutOfMemoryError를 발생 시켰는지는 알 수 없는 것입니다.

 

따라서 이런 경우는 정확한 분석을 위해 Heap의 메모리 정보를 분석할 수 있는 Heapdump를 생성하여 분석하는 것이 가장 확실한 방법입니다. 또한 GC Log를 통해 Heap 메모리의 Leak 여부도 확인하는 것도 도움이 되는 방법입니다.

 

javacore 파일을 통해 문제를 해결하기 가장 좋은 경우는 프로세스 Hang일 경우이며 이 Hang이 동기화(Synchronization)에 의한 부분이라면 더욱 효과적인 정보가 됩니다.

 

이렇게 Sun계열과 IBM 계열에 대한 Thread dump 에 대해 알아 보았습니다.

 

 

Posted by yysvip

최근에 달린 댓글

최근에 받은 트랙백

글 보관함