'Technical Note'에 해당되는 글 134건

Technical Note/SERVER PERFORMANCE

JDK에 포함된 jmap 명령으로 실행 중인 JVM의 heap 상태를 확인해보자.


먼저 실행중인 JVM의 프로세스 ID를 알아야 한다. JDK에 포함된 jps 명령을 사용하거나 "ps -ef | grep java"를 사용한다.

$ jps

14895 Bootstrap

20658 Jps


JVM의 heap 상태를 확인할 때는 -heap 옵션을 사용한다.

$ jmap -heap 14895

Attaching to process ID 14895, please wait...

Debugger attached successfully.

Server compiler detected.

JVM version is 20.2-b06


using thread-local object allocation.

Parallel GC with 4 thread(s)


Heap Configuration:

   MinHeapFreeRatio = 40

   MaxHeapFreeRatio = 70

   MaxHeapSize      = 1073741824 (1024.0MB)

   NewSize          = 1048576 (1.0MB)

   MaxNewSize       = 4294901760 (4095.9375MB)

   OldSize          = 4194304 (4.0MB)

   NewRatio         = 2

   SurvivorRatio    = 8

   PermSize         = 16777216 (16.0MB)

   MaxPermSize      = 268435456 (256.0MB)


Heap Usage:

PS Young Generation

Eden Space:

   capacity = 268500992 (256.0625MB)

   used     = 4983224 (4.752372741699219MB)

   free     = 263517768 (251.31012725830078MB)

   1.8559424912664755% used

From Space:

   capacity = 44695552 (42.625MB)

   used     = 0 (0.0MB)

   free     = 44695552 (42.625MB)

   0.0% used

To Space:

   capacity = 44695552 (42.625MB)

   used     = 0 (0.0MB)

   free     = 44695552 (42.625MB)

   0.0% used

PS Old Generation

   capacity = 715849728 (682.6875MB)

   used     = 49058464 (46.785797119140625MB)

   free     = 666791264 (635.9017028808594MB)

   6.853179107445299% used

PS Perm Generation

   capacity = 67895296 (64.75MB)

   used     = 67656232 (64.52201080322266MB)

   free     = 239064 (0.22798919677734375MB)

   99.64789313239021% used


Heap 설정과 각 Generation 별 사용 현황을 확인할 수 있다. 만약 Old Generation의 사용량이 지속적으로 증가한다면 memory leak을 의심할 수 있다. 


이 때, -histo 옵션으로 클래스별 객체 수와 메모리 사용량을 확인할 수 있다. 

$ jmap -histo:live 14895 | more


num     #instances         #bytes  class name

----------------------------------------------

   1:        146470       18465136  <constMethodKlass>

   2:        146470       12896024  <methodKlass>

   3:        136294       12627544  [C

   4:         29162        8543584  [B

   5:         13655        7868184  <constantPoolKlass>

   6:        157523        7785024  <symbolKlass>

   7:         13655        5912264  <instanceKlassKlass>

   8:         10783        4518792  <constantPoolCacheKlass>

   9:        136440        3274560  java.lang.String

  10:         27292        2066056  [Ljava.util.HashMap$Entry;

  11:         20292        1623360  java.lang.reflect.Method

  12:         31501        1570240  [I

  13:         14653        1406688  java.lang.Class

  14:         23864        1336384  org.objectweb.asm.Label

  15:         27767        1332816  org.objectweb.asm.Item

  16:         39861        1275552  java.util.LinkedHashMap$Entry

  17:         53115        1274760  org.objectweb.asm.Edge

  18:         21894        1226064  org.objectweb.asm.Label

  19:         25335        1216080  org.objectweb.asm.Item   


주기적으로 클래스별 객체 수와 메모리 사용량을 체크해보면 어느 클래스의 객체가 누수되고 있는지 쉽게 알 수 있다. 하지만, 어디에서 누수를 일으키는지는 jmap 만으로는 알 수 없고, heap dump를 떠서 분석해야 알 수 있다.


이제 -dump 옵션으로 heap dump를 뜬 후, MAT 등으로 분석한다.

 $jmap -dump:format=b,file=heap.14895.hprof 14895

[출처] jmap으로 JVM heap 상태 확인|작성자 소프


Technical Note/SERVER PERFORMANCE

Java 플랫폼의 감시와 관리
- JMX를 사용하여 감시하는 방법

ClassLoadingMXBean
CompilationMXBean
GarbageCollectorMXBean
MemoryManagerMXBean
MemoryMXBean

인터페이스 개요
ClassLoadingMXBean     Java 가상 머신의 클래스 로딩 시스템의 관리 인터페이스입니다.
CompilationMXBean     Java 가상 머신의 컴파일 시스템의 관리 인터페이스입니다.
GarbageCollectorMXBean     Java 가상 머신의 가비지 컬렉션의 관리 인터페이스입니다.
MemoryManagerMXBean     MS-DOS메모리 관리 프로그램 관리 인터페이스.
MemoryMXBean     Java 가상 머신의 메모리시스템의 관리 인터페이스입니다.
MemoryPoolMXBean     메모리프르의 관리 인터페이스입니다.
OperatingSystemMXBean     Java 가상 머신을 실행하고 있는 operating system의 관리 인터페이스를 돌려줍니다.
RuntimeMXBean     Java 가상 머신의 실행시 시스템의 관리 인터페이스입니다.
ThreadMXBean     Java 가상 머신의 thread 시스템의 관리 인터페이스입니다.

JMX 에서 standardbean 사용 관련 Tip
Standard mbean을 만들기 위해서는 inteface로 먼저 MBean을 만들고, 그 구현체에서 interface를 상속하고 구현을 하도록 가이드가 되어 있다.



http://knight76.tistory.com/entry/30045067133
http://blog.naver.com/PostView.nhn?blogId=eemmjj2k&logNo=140119003065&categoryNo=25&parentCategoryNo=25&viewDate=&currentPage=1&postListTopCurrentPage=&userTopListOpen=true&userTopListCount=5&userTopListManageOpen=false&userTopListCurrentPage=1
http://www.jjangu.pe.kr/javaApi/javax/management/package-summary.html
http://www.jjangu.pe.kr/javaApi/javax/management/remote/rmi/package-summary.html
http://xrath.com/javase/ko/6/docs/ko/api/javax/management/package-summary.html


Technical Note/SERVER PERFORMANCE

- JVM과  JVM의 가비지 컬렉터가 대부분의 메모리 관련 작업을 처리한다 해도 메모리 손실이 발생할 수 있음

- GC : 루트 객체 (스택, 정적필드, JNI 핸들 등에 대한 객체) 에서 오는 모든 참조를 반복적으로 추적한 다음, 접근 가능한 모든 객체를 활성 상태로 표시
이렇게 표시된 객체만 프로그램에서 조작할수 있으며, 다른 객체는 삭제됩니다. 안전을 위해서 GC는 삭제된 객체에 프로그램이 접근할 수 없도록 합니다

- 메모리 관리 기능이 자동으로 수행된다고 하더라도 프로그래머는 메모리 관리와 관련된 문제를 늘 염두해 두어야 한다. 
- 메모리 할당하고 비우는 작업은 항상 비용과 관련
- 객체를 너무 많이 생성한 프로그램은 객체를 적게 생성하는 프로그램보다 속도가 느림
- 이미 할당된 메모리를 비우는것을 잊어버릴 경우에도 메모리 손실이 발생
- 사용하지 않을 객체에 대한 참조를 계속 유지할 경우 이런 객체는 주변에 머물며, 멤모리를 계속 소모하게 되는데 GC는 이 객체가 더이상 사용되지 않을것임을 알수있는 방법이 없다.
- 객체에 대한 참조가 존재한다면, 그 객체는 당연히 활성 상태 일 것이고 따라서 삭제되지 않을것이다
- 객체의 메모리를 회수하려면 더이상 해당 객체에 접근할수없도록 해야 함
- 이를 위해서 전형적인 방법은 객체의 필드를  null로 설정하거나 객체를 컬렉션에서 제고하는것 

메모리 릭의 유형과 그 원인



--------------------------------------------------------------------
  1. memory 사용율은 어느정도 인가?
  2. gabage collection은 잘 작동하고 있는가?
  3. jvm 설정 정보가 적절한가?
  4. Memory Leak 이 발생하지는 않는가?
  5. 만약 Memory Leak이 발생하였다면, Native stack, Heap, Perm 중 어느 영역이 문제인가?
  6. 또한 Memory Leak의 원인은 무엇인가?
  7. Thread 상태가 어떤가?
JVM 모니터링 항목 

메모리 모니터링을 시작 한다고 하면 제일 먼저 보는 항목은 무엇일까?
> 메모리 할당 정보 --> 아! 이정도 Heap 사이즈를 할당했구나..
그렇다면 메모리가 문제없이 잘 처리하고 있는가 확인해 볼까?
> GC를 보자 
GC의 어떤것을 보아야 하는가? 
> Young 영역에서 Old 영역으로 언제 얼마나 이동을 하는가? /  Stop-the-World가 언제 일어나고 얼마 동안 일어나고 있는가?


모니터링 방법에는 접근 인터페이스에 따라 CUI와 GUI로 구분이 된다.
CUI : jstat, jps, jstatd / JVM 을 가동할 때 '-verbosegc' 라는 JVM 옵션을 이용
GUI : Jconsole, jvisualVM, VisualGC

jstat : GC 수행 정보, 클래스 로더 수행 정보, heap 영역의 크기 변화 등
jps : vmid 와 main 메서드 정보 등
-verbosegc 옵션  : 직관적으로 이해하기 쉬운 출력 결과를 GC가 발생할 때마다 보여 주기 때문에 개략적인 GC 정보를 모니터링할 때에는 아주 좋다.
Jmap : Obejct  누수를 찾을때 지정된 시점의 힙에 대한 덤프  --> 힙의 스냅샷 (-histo) 옵션 : 힙에서 강력하게 참조된 오브젝트에 대한 텍스트 히스토그램 생성

표 3 jstat과 -verbosegc 옵션 비교
 

jstat

-verbosegc 옵션

모니터링 대상

터미널에 로그인할 수 있는 머신에서 가동 중인 Java 애플리케이션이거나 jstatd를 통하여 네트워크로 연결할 수 있는 리모트 Java 애플리케이션

JVM 시작 옵션으로 -verbosegc를 지정한 Java 애플리케이션에 대해서만

출력 정보

힙 상태(사용량, 최대 크기, GC 횟수/시간 등)

New 영역과 Old 영역에 대한 GC 이전/이후 크기와 수행 시간

출력 시기

지정한 시간 간격마다

GC가 발생할 때마다

유용할 때

힙 영역의 크기 변화를 관찰할 때

한 번의 GC에 대한 효과


Jhat : 힙 데이터를 분석

java visualVM : oracle JDK 가 제공하는 GUI 프로파일링/모니터링 툴
visualVM : 홈페이지에서 직접 내려 받은 GUI 프로파일링/모니터링 툴

JConsol : JMX 기술을 이용한 툴
JMeter : JVMTI 기반 기술을 이용한 툴


---------------------------------------------------------------
  1. memory 사용율은 어느정도 인가?
  2. gabage collection은 잘 작동하고 있는가?
  3. jvm 설정 정보가 적절한가?
  4. Memory Leak 이 발생하지는 않는가?
  5. 만약 Memory Leak이 발생하였다면, Native stack, Heap, Perm 중 어느 영역이 문제인가?
  6. 또한 Memory Leak의 원인은 무엇인가?
  7. Thread 상태가 어떤가?



기준 HotSpot JVM 을 기준으로 할것임


JVM 모니터링 항목을 보안
1. JVM 모니터링 항목

일반적인 JVM 모니터링 항목

1. JVM 설정 정보는 어떤가?   -->  Jinfo, Java Process  확인  / Jconsole
   - Heap Size 는 얼마인가?
   - GC 알고리즘은 어떤것인가?
   - 어떤 옵션을 사용하고 있는가?

2. Memory 사용율을 어느 정도인가? -->  jstat  /Jconsole

3. gabage collection은 잘 작동하고 있는가? --> jstat, '-Xverbose:gc 라는 JVM 옵션 / Jconsole
   - Young 영역에서 Old 영역으로 언제 얼마나 자주 이동을 하는가? 
   - GC Time 이 얼마나 걸리는가?

4. Memory Leak 이 발생하지는 않는가? --> jstat, jmap, jhat / Jconsole
   - FGC시 old  영역이 줄어들지는 않는가?
   - 사용하지 않을 객체가 계속 참조되고 있지는 않는가?

5. Thread 상태가 어떤가? --> jstack / Jconsole


2. 모니터링 방법
모니터링 방법에는 접근 인터페이스에 따라 CUI와 GUI로 구분이 된다.
CUI : jstat, jps, jstatd / JVM 을 가동할 때 '-Xverbose:gc 라는 JVM 옵션을 이용 / jmap / jhat
GUI : Jconsole, jvisualVM, VisualGC

jmx를 기반으로 개발한 도구로 jconsole이 있는데
모니터링 항목은
1. threads : Live threads, peak threads, Thread 상태 
2. Classes : 현재 로딩된  class 수 
3. memory : 메모리 통계
4. GC
5. 운영체제 정보

5. 추가적으로 모니터링을 하고 싶은것 (위의 방법들로는 못하는것)
- 메모리 LEAK 을 실제로 발견하게 되면 손실의 원인을 찾아내기 위한 도구가 필요
- 이러한 도구들이 jvm의 정보를 수집하는 방법으로 사용하는 기술이 두가지가 있는데 jvmti 와 바이트코드 조작 이다.


6. 그럼 어떤 기술을 통해서 모니터링 해야 하는가

JMX/JVMTI 


Technical Note/SERVER PERFORMANCE

Needs에 맞는 패턴 활용

켄트 벡의 구현 패턴 : 가까운 시일내에 읽어볼 예정임

VO패턴이나 Service-Locator패턴은 반드시 사용하자

리팩토링

마틴 파울러의 리팩토링 : 역시 가까운 시일내에 읽어볼 예정임

garbage collection에 대한 이해

메모리(변수, 객체) 할당/해제에 대해 신경을 써야 한다

절대 System.gc()를 써서 명시적으로 gc를 요청하면 안된다

JVM의 gc 관련 옵션으로 상황에 맞는 gc방법을 지정하여 성능 향상을 꾀할 수 있다

gc 모니터링/분석을 위한 Tool과 방법

  • jvmstat : SUN에서 제공하는 무료 툴, jdk1.4.2이상이면 바로 사용가능, jdk1.4.1이면 -XX:+UsePerfData 옵션을 사용하면 됨
  • visualgc : SUN에서 제공하는 무료 툴
  • java -verbosegc옵션
  • jps : jvm 프로세스를 보여줌
  • jstat : jvm 통계수치를 보여줌
  • jstatd : 원격으로 jstat을 사용하기 위한 데몬
[참고]/lib/security/java.policy에 다음을 추가해야 jstatd 사용가능함

grant codebase &quot;file:${java.home}/../lib/tools.jar&quot; {
        permission java.security.AllPermission;
};

프로파일링과 APM 툴의 활용

  • 프로파일링 툴(Profiling Tool) : 소스 레벨 분석용, DevPartner for Java, JProbe, TPTP(Eclipse용)
  • APM(Application Performance Monitoring or Management) : 애플리케이션 실행 상황 모니터링/문제점 진단용, Jennifer, IntroScope, I3, Vantage Analyzer

System Class 활용

arraycopy

Property관련 : getProperties, getProperty, setProperties, setProperty

Native Library 관련 : load, loadLibrary

gc관련 : gc, runFinalization

시간 관련  : currentTimeMilis, nanoTime

String, StringBuffer, StringBuilder

  • String : 짧은 문자열 더할때
  • StringBuffer : Thread-Safe가 필요할 때
  • StringBuilder : Thread-Safe가 필요없을때

Collection & Map

적절한 자료구조를 선택해서 사용하라

대용량 데이타가 아닌 경우 성능차이는 그다지 크지 않다, 대용량 데이터의 경우는 간략한 테스트 후 선택한다

Sun의 추천 목록 : HashSet, ArrayList, HashMap, LinkedList

종류

  • Collection : 최상위 클래스
  • Set : 중복불허 집합
  • SortedSet : 오름차순 정렬 Set
  • List : 순서가 있는 Set
  • Queue : FIFO구현, 객체 순차 처리용으로 많이 사용
  • Map : 키-값 쌍으로 구성된 객체 Set, 중복키 불허
  • SortedMap : 키를 오름차순 정렬하는 Map
  • HashSet : 데이타를 Hash Table에 저장, 순서없슴
  • TreeSet : red-back 트리에 저장
  • LinkedHashSet : 저장된 순서대로 순서가 결정되는 HashSet
  • Vector : 크기 지정필요없는 배열
  • ArrayList : 동기화 처리 안됨, Vector와 비슷
  • LinkedList : ArrayList와 동일 + Queue인터페이스 구현
  • HashTable : 데이터를 해쉬테이블에 저장, 동기화됨
  • HashMap : null값 허용 + 동기화안됨을 제외하고는 HashTable과 동일
  • TreeMap : red-back 트리에 데이터를 저장, TreeSet과 다른 점은 키에 의해 순서가 정해짐
  • LinkedHashMap : Double-Linked List방식을 제외하고 HashMap과 동일
  • PriorityQueue : 큐에 추가된 순서가 아니라 객체 생성 순서대로 Pop되는 Queue
  • LinkedBlockingQueue : FIFO기반의 Linked 노드를 사용하는 Blocking Queue
  • ArrayBlockingQueue : 크기 정해짐, FIFO기반 Blocking Queue
  • PriorityBlockingQueue : 크기 안 정해짐, 객체 생성 순서대로 Pop되는 Queue
  • DelayQueue : 대기시간을 정할 수 있는 Queue
  • SynchronousQueue : put()호출하면, 다른 thread에서 take()해줄때까지 대기하는 Queue

동기화 여부

  • 동기화됨 – Vector, HashTable
  • 동기화안됨 – HashSet, TreeSet, LinkedHashSet, ArrayList, LinkedList, HashMap, TreeMap, LinkedHashMap

동기화안된 Collection을 위한 메쏘드 : Collections.synchronizedXXX (XXX = Set, SortedSet, List, Map)

Loop 성능 향상

if나 switch나 성능은 비슷, 가독성 측면만 고려하면 됨

Loop안에서의 쓸데없는 변수/객체 생성, 메쏘드 호출을 최대한 제거

for loop 구현방법 : 속도 : Code #1 < Code #2 < Code #3

Code #1

for(int i = 0; i < arrData.length(); i++)

Code #2

Vector v = …

for(String str : v )

Code #3

int intLength = arrData.length();

for(int i = 0; i < intLength; i++)

static

static 선언된 변수 : 객체가 아니라 클래스에 속함, 모든 객체가 동일한 변수 1개를 참조하게 됨, gc도 이뤄지지 않음

static 블럭 : 생성자와 상관없이 최초 1회 실행됨

자주 사용, 절대 변하지 않는 변수는 final static으로 선언

설정파일정보도 static으로 관리하는 것이 좋다

code성 데이타는 DB에서 1회 읽도록 한다

synchronized

하나의 객체를 여러 Thread에서 사용해야 하는 경우 -> 해당 객체에 접근하는 method에 synchronized 선언

static으로 선언된 객체를 여러 Thread에서 사용해야 하는 경우 -> 해당 객체에 접근하는 method에 static synchronized 선언

java.util.Concurrent 패키지를 이용해서 Thread관리 – Lock, Executors, Concurrent Collection, Atomic 변수

reflection class를 통해 클래스 정보 등을 얻을 수 있다

Class, Method, Field

JMX와 함께 모니터링 부분 구현 가능

IO병목 해결

설정파일 사용시 매번 갱신여부 확인하는 대신에 데몬 쓰레드로 주기적 점검하는 식으로 구현

파일 복사 or 네트워크 작업시 NIO이용

개인적으로는 Netty 이용할 예정

Logging

상용 배포전에 모두 제거하는 게 Best

로깅여부 Flag(final로 선언)를 둬서 Logging

System.out.println대신에 Logger or Log4j를 이용

Exception처리시에도 printStackTrace대신에 Exception에서 필요한 부분만 로깅하도록 구현

DB사용

Connection Pool or Data Source 사용하여 Connection 관리

사용가능할 경우, Statement보다 PreparedStatement를 주로 사용

Connection, Statement, ResultSet 관리 철저 : 생성시 Connection – Statement – ResultSet순, 닫을때는 역순

Connection conn = null;
Statement stmt = null;
ResultSet rs = null;

try {
        ...
} catch (Exception e) {
        ...
} finally {
        try { rs.close(); rs = null; } catch ( Exception e ) {}
        try { stmt.close(); stmt = null; } catch ( Exception e ) {}
        try { conn.close(); conn = null; } catch ( Exception e ) {}
}

ResultSet의 last()는 절대 사용불가 : 차라리 데이터 개수 확인을 위해 쿼리를 날려라 or 배열 대신에 Vector를 사용해서 데이타를 리턴

데이터 조작없이 조회만 하는 경우는 setAutoCommit()를 사용하지 말자

배치성 작업을 위해서는 executeBatch()를 이용하자

setFetchSize()를 이용해서 적당한 개수를 Fetch하도록 직접 지정하자

1건이 필요하면, 1건만 쿼리하라

XML 관련

SAX : 이벤트에 맞춰 순차적으로 처리, 트리 따라다니기기 쉽지 않음, 메모리 사용량은 적음

DOM : 전체 xml 내용을 트리로 만들어 메모리에 적재, 전체를 메모리에 올리므로 메모리 사용량 많음

웹서버 관련

httpd.conf 설정내용

Include conf/extra/httpd-mpm.conf

KeepAlive On

KeepAliveTimeout 15

HostnameLookups는 무조건 off

로그 포맷에 %D(요청처리시간을 마이크로초 단위로 표시), %T(요청처리시간을 초 단위로 표시)

httpd-mpm.conf

<IfModule mpm_worker_module>

StartServers : 최초에 띄울 프로세스의 수

MaxClients : 최대 처리 가능한 클라이언트의 수

MinSpareThreads : 최소 여유 쓰레드 수

MaxSpareThreads : 최대 여유 쓰레드 수

ThreadsPerChild : 프로세스당 쓰레드 수

MaxRequestsPerChild : 프로세스당 최대 요청 수

</IfModule mpm_worker_module>

웹로그 분석 : Analog, AWStats, Webalizer

정적인 내용(이미지, 플래시, 자바스크립트 등)이 많을 경우에는 따로 서버를 두어 해결하는 방안도 고려

DB Connection Pool 설정

Thread수는 Connection 개수보다 10개 정도 많게 설정

session timeout을 설정하자

JVM설정

jvm에 메모리 설정 -Xmx는 최대 메모리, -Xms는 최소 메모리

inspection tool

Hammurapii, PMD. CheckStyle

모니터링 API JMX

Jconsole은 JMX 모니터링용 툴(Sun에서 제공)

JMX 원격 모니터링을 위한 VM옵션

-Dcom.sun.management.jmxremote.port=9003

-Dcom.sun.management.jmxremote.password.file=/파일위치

-Dcom.sun.management.jmxremote.access.file=/파일위치

-Dcom.sun.management.jmxremote.ssl=false

문제 진단을 위한 참고사항

http://java.sun.com/javase/6/webnotes/trouble/other/matrix6-Windows.html

http://java.sun.com/javase/6/webnotes/trouble/other/matrix6-Unix.html


Related posts:

  1. 자바 코딩 규약 정리 한 줄에 한 문장만 써라 //가독성이 떨어짐 int i; System.out.println("Hello...
  2. Netty 사용에 관한 몇가지 Tip ClientBootStrap 설정 샘플 bootstrap = new ClientBootstrap( new NioClientSocketChannelFactory(Executors.newCachedThreadPool(), Executors.newCachedThreadPool()));...
  3. 안드로이드 어플의 VersionName (버전 번호)을 AndroidManifest.xml에서 가져오기  public static String getVersionName(Context context) {     try {        ...
  4. ImageButton with selector & style 상속 http://www.androidpub.com/55225   <?xml version="1.0" encoding="utf-8"?> <selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:state_pressed="true" android:drawable="@drawable/navy"...
  5. java 서버용 어플리케이션의 자동 업데이트, 자동 재실행, db/config변경 및 프로세스 종료시 자동 시작 구현을 위한 아이디어 실행할 프로세스를 직접 실행시키지 않고 별도의 매니지먼트용 프로세스를 두어서 매니지먼트...


Technical Note/JAVA

아마도 윈도우에서 (리눅스나 Unix계열도 마찬가지로) javaw.exe로 실행 시킨 프로그램이나 EclipseNetBeans등의 개발 도구에서 내부 콘솔로 띄운 프로그램 혹은 서비스(데몬)로 띄운 프로그램의 쓰레드 덤프를 얻고 싶은데, 어떻게 해야 할지 몰라 당황한 적이 있을 것이다.

이미 떠있는 JVM의 스택 트레이스(Stack Trace 혹은 쓰레드 덤프 Thread Dump)를 뜨기 위한 개발 도구가 생겼다.

jstack

쓰레드 덤프 하기

 

이 툴은 아주 효과 만점이다.

kill -3 자바프로세스번호 하면서 고생하던 것을 쉽게 해결해준다.

 

치면 이렇게 나온다.

 

Usage:
    jstack [-l] <pid>
        (to connect to running process)
    jstack -F [-m] [-l] <pid>
        (to connect to a hung process)
    jstack [-m] [-l] <executable> <core>
        (to connect to a core file)
    jstack [-m] [-l] [server_id@]<remote server IP or hostname>
        (to connect to a remote debug server)

Options:
    -F  to force a thread dump. Use when jstack <pid> does not respond (process is hung)
    -m  to print both java and native frames (mixed mode)
    -l  long listing. Prints additional information about locks
    -h or -help to print this help message

 

강제로, native영역과 함께, 특히 deadlock 여부까지!! 오호! 굿

 

테스트 해보자. 물론 리눅스 환경에서. (윈도우도 되겠지만)

/usr/local/jdk6/bin/jps v             // ps -ef | grep java와 같다.

 /usr/local/jdk6/bin/jstack 21720 > td.txt    // java 프로세스 넘버주면, 파일로 덤프가 가능하다.

 

/usr/local/jdk6/bin/jstack -l 21720 > td.txt   // 이렇게 하면,  deadlock까지 체크!

 


Unix/Linux 계열은 Java 5부터 (실질적으로는 JDK 1.4.2_11 도 포함하고 있다고 한다) jstack 이라는 프로그램이 JDK에 포함되었다.
하지만, Windows 용 JDK는 Java 6 부터 포함되었다.

이것은 이미 떠 있는 JVM 프로세스에서 쓰레드 덤프를 뜰 수 있게 해주는 유틸리티이다.
문제는 사실, Unix/Linux 계열에서는 이런 도구가 없어도 어느정도 kill -3 명령으로 쓰레드 덤프 뜨는게 가능 했고, 정작 javaw.exe나 혹은 서비스로 뜬 JVM의 쓰레드 덤프를 뜰 수 있는 방법이 거의 없는(있기는 있다) 윈도우용은 Java 6 이상이어야만 사용 가능하다는 점이다.

아무튼....
먼저 jps 라는 명령으로 JVM의 프로세스 번호를 얻어온다.
C:\Java\jdk1.6.0\bin>jps --help
illegal argument: --help
usage: jps [-help]
       jps [-q] [-mlvV] [<hostid>]

Definitions:
    <hostid>:      <hostname>[:<port>]

C:\Java\jdk1.6.0\bin>jps -v
3280 Jps -Dapplication.home=C:\Java\jdk1.6.0 -Xms8m
4740 startup.jar -Xms40m -Xmx256m

그리고는 jstack 명령에 PID를 지정해주면 해당 PID를 가진 JVM의 Stack Trace를 얻게 된다.
C:\Java\jdk1.6.0\bin>jstack 4740 > st.txt

/usr/local/jdk6/bin/jstack -l 21720 > td.txt   // 이렇게 하면,  deadlock까지 체크!


Stack Trace는 당연히 st.txt 파일에 저장되어 있다.

jstack에 대한 소개는 Alan Bateman의 jstack이라는 블로그 글에서 보았다.

Stack Trace

그렇다면 Windows 에서 Java 5, 1.4 등의 Stack Trace를 얻을 수 있는 방법은 없을까? 있다.
가장 간단한 방법은 Stack Trace라는 프로그램을 이용하는 것이다. 원래는 상용이지만 Java Web Start로 설치하면 회사에서도 무료로 이용하게 되어 있다.

jconsole

두번째 방법으로 Java 5의 jconsole을 이용하는 방법이 있다.
Java 어플리케이션을 실행할 때 시스템 프라퍼티(System property)로 com.sun.management.jmxremote를 지정해서 실행하면 된다.
다음은 eclipse.ini 파일에 -vmargs 의 부가 옵션으로 -Dcom.sun.management.jmxremote를 지정해서 Eclipse를 실행한 뒤(Windows XP라면 방화벽에서 예외로 지정해야 한다)에 jconsole로 본 것이다. jconsole은 그냥 jconsole.exe를 실행하기만 하면 된다.

* jconsole을 실행하여, 모니터링할 JVM을 선택한다.


* 해당 JVM의 쓰레드 상태를 살펴본다.



1 ··· 22 23 24 25 26 27
블로그 이미지

zzikjh