Study...★/Java2011. 7. 4. 13:47

가비지 콜렉션 소개

참고: 이 기사에서 설명하는 조정 작업을 올바르게 수행하려면 최신 서비스 릴리스의 SDK나 적어도 SR13 이상의 서비스 릴리스를 사용해야 한다.

가비지 콜렉션은 프로세스에서 더 이상 참조 또는 사용하지 않는 오브젝트로 구성된 힙 즉, Java 애플리케이션에서 자원 관리를 위해 사용되는 정의된 메모리 섹션을 제거하는 JVM(JavaTM Virtual Machine)의 동작이라고 간단히 정의할 수 있다.

이 프로세스에는 다음과 같은 표시, 제거 및 압축이라는 세 가지 주요 단계가 있다.

  • 표시 단계에서는 힙의 모든 오브젝트가 비트를 사용하여 "표시"된다. 오브젝트를 검사하여 오브젝트가 참조되고 있으면 비트가 제거된다.
  • 제거 단계에서는 JVM이 힙 전체를 이동하면서 표시 비트가 설정되어 있는 모든 오브젝트를 제거한다. 이러한 오브젝트는 더 이상 참조 또는 사용되지 않는다.
  • 압축 단계는 전체 GC에서만 실행된다. 이 단계에서는 힙의 모든 오브젝트를 힙의 더 작고, 압축되고, 연속적인 공간에 다시 할당한다.

가비지 콜렉션의 작동 방법

힙 사용 상태를 검사하는 최상의 방법은 verbose GC 출력을 분석하는 것이다.

먼저 다음과 같이 verbose GC가 서버에서 사용되고 있는지 확인하자.

  1. IBM WebSphere Application Server 관리 콘솔에서 Application Servers - WebSphere_Portal - Java and Process Management - Process Definition - Java Virtual Machine으로 이동한다.
  2. Verbose garbage collection 옆의 선택란이 선택되어 있는지 확인한 다음 서버를 다시 시작한다.
  3. 이제 native_stderr.log 파일에서 다음과 같은 유사한 항목을 볼 수 있다.
    <AF[177]: Allocation Failure. need 528 bytes, 3602594 ms since last AF>
    <AF[177]: managing allocation failure, action=1 (0/585421800) (29966688/30811672)>
    <GC(177): GC cycle started Fri Sep 21 23:48:29 2007
    <GC(177): freed 218620376 bytes, 40% free (248587064/616233472), in 459 ms>
    <GC(177): mark: 422 ms, sweep: 37 ms, compact: 0 ms>
    <GC(177): refs: soft 0 (age >= 32), weak 11, final 7424, phantom 0>
    <AF[177]: completed in 460 ms>

로그 파일 항목 분석하기

이제 앞의 로그 항목을 섹션별로 살펴보면서 그 의미를 확인해 보자.

먼저 첫 번째 행부터 살펴보자.

<AF[177]: Allocation Failure. need 528 bytes, 3602594 ms since last AF>

이 항목은 할당이 실패했음을 알려주며, 힙에 오브젝트를 할당할 수 있는 연속 공간이 충분하지 않을 경우에 표시된다. 이 오브젝트는 verbose GC 출력에서 가장 일반적으로 볼 수 있는 조치이다. 이 경우에는 528바이트의 작은 오브젝트였다.

또한 이 행에서는 GC 사이클을 마지막으로 실행한 이후 3602594밀리초가 경과되었음을 알 수 있다.

다음으로 마지막 행을 살펴보자.

<AF[177]: completed in 460 ms>

이 행은 GC에서 경과된 시간을 보여 준다. 이 숫자를 사용하면 마지막으로 GC에 있었던 시간의 비율과 GC를 수행한 시간의 백분율(실제 작업 시간이 아님)을 구할 수 있다. 예를 들면, 다음과 같다.

460/3602594 = .000127% of the time was spent in GC

정상 상태의 서버에서는 GC에 사용되는 시간의 백분율이 13% 미만, 이상적으로는 약 7-10%가 되어야 한다.

두 번째 행으로 돌아가자.

<AF[177]: managing allocation failure, action=1 (0/585421800) (29966688/30811672)>

여기에서 가장 먼저 살펴볼 내용은 "action=" 값이다. 다음과 같은 7개의 조치가 할당 실패 시 발생할 수 있다.

  • action=0은 pinnedFreeList가 소진되었음을 의미한다.
  • action=1은 우선적 가비지 콜렉션 주기를 의미한다.
  • action=2는 전체 할당 실패를 의미한다.
  • action=3은 힙 확장이 발생했음을 의미한다.
  • action=4는 알려진 모든 소프트 참조가 지워졌음을 의미한다.
  • action=5는 임시 힙의 공간을 가져오는 작업이 완료되었음을 의미한다.
  • action=6은 여유 공간이 매우 적다는 것을 의미한다.

이러한 조치는 심각도 순으로 나열되었으며 가장 심각한 조치는 서버에 여유 메모리가 전혀 없을 때 발생한다(action=6).

이 경우에는 action=1이다. 이 유형의 GC에서는 GC의 표시 및 제거 단계만 실행된다.

이 행에는 다음과 같은 내용도 있다.

(0/585421800) (29966688/30811672)

이 행은 AIX® JVM과 관련되어 있다. 이 행에는 두 개의 기수가 있으며, 두 수를 합한 값은 확장된 힙의 크기이다. 둘 중 작은 수가 자동으로 대형 오브젝트 할당에 사용된다.

참고: 대형 오브젝트는 64KB 이상의 오브젝트를 의미한다.

다른 모든 오브젝트는 힙의 다른 섹션에 저장된다. 대형 오브젝트 섹션이 모두 채워진 상황에서 다른 대형 오브젝트가 할당을 요청할 경우 이 오브젝트는 힙의 다른 기본 섹션에 저장된다. 이 오브젝트는 다른 플랫폼 JVM의 유용한 조정 매개변수일 수 있으며 -Xloratio라고 한다.

다음 행의 내용은 다음과 같다.

<GC(177): GC cycle started Fri Sep 21 23:48:29 2007

이 행은 GC 주기의 시작 시간과 현재 주기 즉, GC(177)를 보고한다. 이는 JVM이 시작된 이후 177번째로 실행된 GC이다.

다음 행의 내용은 다음과 같다.

<GC(177): freed 218620376 bytes, 40% free (248587064/616233472), in 459 ms>

이 행에서는 GC 주기 동안 사용 가능하게 된 바이트 수를 알려 준다. 이 경우에는 JVM이 218620376바이트를 사용 가능하게 할 수 있었다.

또한 힙의 40%가 여유 공간임을 알 수 있다. 즉, 616,233,472바이트의 전체 힙 크기 중 248,587,064바이트가 여유 공간이다.

(248587064/616233472)

마지막으로 GC 주기가 완료되는 데 459밀리초가 소요되었다.

이 행은 힙의 여유 공간 용량을 알려 주고, 정리되어 힙에 고정되지 않은 오브젝트가 있음을 알려 주기 때문에 유용하다.

다음 행의 내용은 다음과 같다.

<GC(177): mark: 422 ms, sweep: 37 ms, compact: 0 ms>

이 행은 이 기사의 뒷부분에서 GC를 구성하여 빠르게 실행되도록 조정할 때(-Xgcpolicy:optavgpause 참조) 사용된다. 하지만 지금은 먼저 다음 사항을 살펴보자.

이 행은 각 주기의 실행 시간을 보여 준다. 표시 단계는 422밀리초, 제거 단계는 37밀리초 그리고 압축 단계는 0밀리초가 소요되었다.

또한 다음 두 가지 사항을 바탕으로 이 GC가 전체 GC가 아님을 알 수 있다.

  • 압축 단계를 완료하는 데 0밀리초가 소요되었다.
  • action=1은 전체 GC가 실행되기 전의 우선적 GC였음을 보여 준다.

마지막으로 살펴볼 행은 다음과 같다.

<GC(177): refs: soft 0 (age >= 32), weak 11, final 7424, phantom 0>

먼저 GC가 오브젝트뿐만 아니라 실제 오브젝트에 대한 별도의 참조 오브젝트도 관리한다는 점을 이해해야 한다. 이러한 참조는 작성 시에 네 큐 중 하나와 연관되며, 이러한 연관은 나중에 변경할 수 없다. 네 개의 큐는 표시 단계 동안 다음과 같은 순서로 표시된다.

  1. Soft
  2. Weak
  3. Final
  4. Phantom

Soft 및 weak 참조는 더 이상 참조되지 않을 경우 정리할 수 있다. 종료자(final 큐)가 soft 또는 weak 참조와 연관된 경우에는 soft 또는 weak 참조가 제거된 후에만 종료자가 실행되는 다음 GC 패스에서 제거된다.

지금까지 살펴본 행은 Java SDK 1.4.2의 기본 GC 정책에서 볼 수 있는 기본 행이다. 지금까지의 설명을 바탕으로 JVM의 실행 방법을 살펴보자.


JVM의 라이프 사이클

JVM은 프로세스를 시작하는 선택적 명령행 인수로 시작된다. 이러한 인수는 WebSphere Application Server 관리 콘솔에서 추가되는 일반 JVM 인수이다.

기본적으로 이 명령은 Java 프로세스가 시작할 때 실행된다.

Java –Xmx1024M –Xms256M –Xverbosegc programToRun

여기서 명령행 인수는 다음과 같다.

–Xmx1024M –Xms256M –Xverbosegc

이는 시작 시에 다음과 같은 사항이 발생한다는 것을 의미한다.

  • 최대 힙 크기가 1024MB이다(–Xmx1024M).
  • 최소 힙 크기가 256MB이다(–Xmx256M).
  • Verbose 가비지 콜렉션이 사용된다(–Xverbosegc).

위의 verbose GC 스니펫에서처럼 JVM에 1024MB를 할당하더라도 전체 1024MB를 사용하게 될 것임을 의미하지는 않는다. 예를 들어, verbose 스니펫에서는 616,233,472바이트만 사용했다.

JVM은 최소 256MB가 할당된 상태로 시작되며 이 공간을 사용한다. 그림 1을 보면 사용하도록 설정된 전체 힙의 크기가 1024MB이다(전체 막대). 하지만 음영 처리된 부분인 초기 256MB만 사용하도록 할당되었다.


그림 1. 힙의 그림 표현
Pictorial representation of the heap

256MB를 사용할 수 있으므로 JVM은 programToRun 프로그램을 실행하는 데 필요한 오브젝트를 사용하여 초기 256MB를 채운다. 이러한 오브젝트는 힙에 저장할 다음 오브젝트에 대한 요청을 충족할 수 있는 연속 공간이 없을 때까지 이 공간에 추가된다(그림 2 참조).


그림 2. 다양한 크기의 오브젝트가 로드된 힙
Heap with different-sized objects loaded

이제 다음 오브젝트가 힙의 공간을 요청한다. 하지만 이 요청을 충족할 수 있는 연속 공간이 부족하다(그림 3 참조).


그림 3. 요청 오브젝트의 그림 표현
Pictorial representation of the requesting object

이 요청이 발생하면 JVM이 action=1 상태로 GC를 실행하며 그림 4와 같이 그림 표현이 변경된다.


그림 4. action=1 상태로 GC를 실행 중인 JVM(사용하지 않은 오브젝트가 제거됨)
JVM running GC with action=1 (note the unused object is removed)

다음과 같이 변경된다.



이제 이 요청을 충족할 수 있다.



때때로 이동 또는 정리할 수 없는 오브젝트도 있다. 즉, 여전히 사용 중인 오브젝트 및 클래스 오브젝트가 있다. 이전 요청과 같은 두 개의 요청이 추가로 발생했다고 가정하자. 하지만 이번에는 힙에서 제거할 수 있는 오브젝트가 하나도 없다(그림 5 참조).


그림 5. 사용 중인 힙의 현재 표현
Current representation of the heap in use

이 경우에는 GC가 압축 단계를 실행하려고 시도하는 action=2를 실행한다. 압축 단계에서는 흩어져 있는 여유 공간을 한 곳으로 모아서 현재 요청을 충족하기 위해 힙에 있는 오브젝트가 통합된다.

그림 6에서는 압축 단계가 완료된 힙을 보여 준다.


그림 6. 압축된 힙
Compacted heap

이제 다음 요청을 할당할 수 있다(그림 7 참조).


그림 7. 작동 중인 힙의 작업 재개
Progression of the working heap continues

이제 GC 조치 1과 2를 살펴보았으므로 조치 1과 2가 모두 실행된 이후라고 하더라도 다음 오브젝트를 할당할 수 있는 공간이 부족할 경우 어떤 상황이 발생하는지 알 수 있다.

일부 오브젝트를 정리할 수 없다고 가정한 상태에서 힙 작업을 계속할 경우 이러한 공간 부족 현상이 발생한다(그림 8 참조).


그림 8. 할당된 공간이 가득 찬 압축된 힙
Compacted heap with the allocated space full

이 그림을 보면 힙의 모든 용량을 사용하고 있다는 것을 알 수 있다. 이 예제에서는 256MB의 힙이 가득 찼으며, 지금까지 256MB만 사용할 수 있는 힙으로 할당했었다. 그러나 앞에서 최대 힙 크기를 1024MB로 설정했으므로 이 상황이 발생할 경우 사용할 수 있는 여분의 힙 용량이 남아 있다.

이 경우 JVM은 action=3을 수행하여 힙을 65,535바이트 확장한다. 이렇게 되면 사용할 수 있는 힙의 용량이 늘어나며(그림 9 참조) 이에 대한 정보가 verbose GC에 표시된다.


그림 9. 65536바이트 확장된 시스템 힙
System heap expanded by 65536 bytes

다음과 같이 변경된다.



이제 처리 작업을 계속 진행할 수 있다. 새로 할당된 모든 힙은 위와 동일한 조치를 거치게 되며, 마지막으로 전체 1024MB에 도달할 때까지 추가 힙이 할당되는 방식으로 GC 주기가 계속 진행된다.

이 방법에서 알 수 있듯이 힙은 작은 용량의 초기 힙부터 시작하여 순차적으로 확장되며, 압축된 형태의 비교적 양호한 상태로 유지된다.

다음은 전체 GC 이후 힙 확장이 발생하는 verbose GC의 예제이다.

<AF[12]: Allocation Failure. need 8208 bytes, 2272 ms since last AF>
<AF[12]: managing allocation failure, action=2 (3255768/52427264)>
  <GC(12): GC cycle started Wed Dec  2 13:55:07 2009
  <GC(12): freed 9836696 bytes, 24% free (13092464/52427264), in 59 ms>
  <GC(12): mark: 50 ms, sweep: 8 ms, compact: 1 ms>
  <GC(12): refs: soft 0 (age >= 32), weak 0, final 102, phantom 0>
<AF[12]: managing allocation failure, action=3 (13092464/52427264)>
  <GC(12): need to expand mark bits for 61602304-byte heap>
  <GC(12): expanded mark bits by 143360 to 962560 bytes>
  <GC(12): need to expand alloc bits for 61602304-byte heap>
  <GC(12): expanded alloc bits by 143360 to 962560 bytes>
  <GC(12): need to expand FR bits for 61602304-byte heap>
  <GC(12): expanded FR bits by 286720 to 1925120 bytes>
  <GC(12): expanded heap by 9175040 to 61602304 bytes, 36% free>
<AF[12]: completed in 75 ms>

지금까지 힙의 확장 방법과 JVM에서 힙을 사용하는 방법에 대해 살펴보았다. 이제 프로세스가 실행되는 동안 JVM에서 실제로 사용하는 메모리의 용량을 살펴보자.


프로세스에 사용되는 메모리 용량 분석하기

프로세스 또는 포털이 런타임 동안 사용하는 메모리 용량에 대한 오해가 발생할 수 있다. 포털 사용자가 ps avg 명령이나 Microsoft® Windows® 작업 관리자를 사용하여 Java 프로세스에서 사용 중인 메모리 용량을 확인하는 경우가 있는데, 이러한 도구는 Java 프로세스에 할당된 메모리 용량을 보여 준다.

지금까지 살펴본 대로 프로세스에 할당된 메모리 용량과 사용 중인 용량은 그 의미가 서로 다르다.

작업 관리자나 "ps avg"에서 Java 프로세스가 616MB를 사용 중인 것으로 표시된 경우 verbose GC를 보면 해당 용량의 40%만 사용되고 있다는 것을 알 수 있다.

<GC(177): freed 218620376 bytes, 40% free (248587064/616233472), in 459 ms>

OUTOFMEMORY 오류와 힙의 여유 공간

OUTOFMEMORY 오류가 발생하고 힙에 여유 공간이 있을 경우 verbose GC를 검사하여 오류의 원인을 파악할 수 있다. 다음 예제는 메모리 부족 오류와 관련된 verbose GC의 출력이다.

<AF[2474]: Allocation Failure. need 16777232 bytes, 114 ms since lastAF>
<AF[2474]: managing allocation failure, action=2(1026078032/1601894912)>
  <GC(2835): GC cycle started Thu Jul 16 11:21:34 2009
  <GC(2835): freed 5827392 bytes, 64% free (1031905424/1601894912), in 2519 ms>
  <GC(2835): mark: 567 ms, sweep: 24 ms, compact: 1928 ms>
  <GC(2835): refs: soft 0 (age >= 32), weak 0, final 6, phantom 0>
  <GC(2835): moved 1711341 objects, 87482984 bytes, reason=1, used 8 more bytes>
<AF[2474]: managing allocation failure, action=3 (1031905424/1601894912)>
  <GC(2835): need to expand mark bits for 1610611200-byte heap>
  <GC(2835): expanded mark bits by 135168 to 25165824 bytes>
  <GC(2835): need to expand alloc bits for 1610611200-byte heap>
  <GC(2835): expanded alloc bits by 135168 to 25165824 bytes>
  <GC(2835): need to expand FR bits for 1610611200-byte heap>
  <GC(2835): expanded FR bits by 270336 to 50331648 bytes>
  <GC(2835): expanded heap fully by 8716288 to 1610611200 bytes, 64% free>
<AF[2474]: managing allocation failure, action=4 (1040621712/1610611200)>
<AF[2474]: clearing all remaining soft refs>
  <GC(2836): GC cycle started Thu Jul 16 11:21:35 2009
  <GC(2836): freed 227346312 bytes, 78% free (1267968024/1610611200), in 1600 ms>
  <GC(2836): mark: 370 ms, sweep: 19 ms, compact: 1211 ms>
  <GC(2836): refs: soft 438 (age >= 32), weak 1178, final 70, phantom 0>
  <GC(2836): moved 1359393 objects, 60973368 bytes, reason=1, used 600 more bytes>
<AF[2474]: managing allocation failure, action=6 (1267968024/1610611200)>
JVMDG217: Dump Handler is Processing OutOfMemory - Please Wait.
JVMDG315: JVM Requesting Heap dump file
JVMDG318: Heap dump file written to
/opt/WebSphere/AppServer/heapdump.20090716.112135.19377.phd
JVMDG303: JVM Requesting Java core file
JVMDG304: Java core file written to
/opt/WebSphere/AppServer/javacore.20090716.112144.19377.txt
JVMDG274: Dump Handler has Processed OutOfMemory.
<AF[2474]: Insufficient space in Javaheap to satisfy allocation request>
<AF[2474]: completed in 19738 ms>

이 예제를 보면 이 인스턴스에 여유 공간이 충분히 있다는 것을 알 수 있다.

<GC(2836): freed 227346312 bytes, 78% free (1267968024/1610611200), in 1600 ms>

하지만 할당 공간을 요청한 오브젝트도 매우 크다.

<AF[2474]: Allocation Failure. need 16777232 bytes, 114 ms since lastAF>

이 유형의 메모리 부족 상황은 k-클러스터(-Xk)를 사용하거나 대형 오브젝트를 위한 힙의 세그먼트를 정의하는 두 가지 방법으로 해결할 수 있다. 여기서, loratio는 대형 오브젝트 비율이다.

-Xkn

이 매개변수는 힙 내에 클래스 오브젝트를 저장할 위치를 별도로 설정한다. 앞의 예제에서 본 것처럼 프로세스에서 사용하고 있는 참조는 이동 또는 정리할 수 없다. 따라서 이러한 참조는 힙의 해당 위치에 "고정"되며 많은 오브젝트가 힙의 다양한 위치에 고정되면 힙이 단편화된다.

이 단편화를 해결하기 위해 –Xkn 매개변수를 사용할 수 있다. 이 매개변수는 힙의 한 섹션을 클래스 오브젝트만을 위한 공간으로 제공한다. 시스템 조정 분석을 위해 WebSphere Portal Support를 사용해야 하기는 하지만 이 매개변수의 n에 적합한 시작 값은 40,000이다.

이 매개변수를 40,000으로 설정하면 JVM이 k-클러스터에 40,000개의 클래스 오브젝트를 저장할 수 있는 공간을 허용한다. 이 k-클러스터가 가득 찰 경우 시스템은 계속해서 정상 상태로 작동하면서 힙의 나머지 부분을 사용하게 된다.

관리 콘솔에서 –Xk를 일반 JVM 인수에 추가하려면 다음 단계를 수행한다.

  1. WebSphere Application Server V6.0에서 Servers - Application Servers - server_name - Java and Process Management - Process definition - Java Virtual Machine - Generic JVM Arguments를 선택한다.

    또는

    WebSphere Application Server V5.0 및 V5.1에서 Servers - Application Servers - server_name - Process Definition - Java Virtual Machine - Generic JVM Arguments를 선택한다.
  2. –Xk40000을 입력하고 이 구성을 저장한 후 서버를 다시 시작한다.

–Xloration

이 설정을 사용하면 힙의 한 섹션을 대형 오브젝트 즉, 64KB 이상의 오브젝트로 정의된 오브젝트에 사용하기 위해 별도로 설정할 수 있다.

그림 예제에서 보았듯이 오브젝트를 사용하려면 힙에 할당할 수 있는 연속 공간이 있어야 한다. 분명 1,000,000바이트의 연속 공간보다는 528바이트의 연속 공간을 더 쉽게 찾을 수 있다.

대형 오브젝트가 힙의 특정 세그먼트에 유지된다면 이러한 오브젝트를 더 쉽게 할당할 수 있으며, 더 나아가 소형 오브젝트가 힙을 사용하기 위해 대형 오브젝트와 경쟁하지 않아도 된다.

이 매개변수의 값은 구현 후 verbose GC를 모니터링하여 조정할 수 있다. 이 매개변수의 값 n은 해당 시점에 확장된 전체 힙에 대한 백분율로 지정된다. 이 예제의 경우에는 –Xloratio0.2라는 값을 사용하자.

이 값이 서버에 추가되면 verbose GC 출력에 다음과 같은 새 행이 추가된다.

<GC(2): heap layout: (424744560/429495496) (107373880/107373880) /0>

다음은 –Xloratio0.2가 활성화된 verbose GC의 블록이다.

<AF[2]: Allocation Failure. need 536 bytes, 235 ms since last AF>
<AF[2]: managing allocation failure, action=0 (423162736/429495496) 
(107373880/107373880)>
  <GC(2): GC cycle started Sat Aug 15 17:07:25 2009
  <GC(2): heap layout:  (424744560/429495496) (107373880/107373880)  /0>
  <GC(2): freed 1581824 bytes, 99% free (532118440/536869376), in 18 ms>
  <GC(2): mark: 9 ms, sweep: 9 ms, compact: 0 ms>
  <GC(2): refs: soft 0 (age >= 32), weak 0, final 0, phantom 0>
<AF[2]: completed in 18 ms>

이제 힙 레이아웃을 볼 수 있으므로 이 행은 이 n 값을 조정하는 방법을 보여 준다.

<GC(2): heap layout: (424744560/429495496) (107373880/107373880) /0>

첫 번째 비율은 힙의 일반 영역이며(일반 작업 처리를 위해 80% 사용), 두 번째 비율은 대형 오브젝트를 위해 정의된 영역이다(대형 오브젝트 할당을 위해 20% 사용).

각 섹션의 여유 공간 용량이 표시된다. 이 출력을 보면 모든 대형 오브젝트 섹션이 사용 가능하며, 사용 중인 대형 오브젝트가 없다는 것을 알 수 있다.

이 추세가 지속될 경우에는 대형 오브젝트 영역을 20%에서 10%로 낮춰서 일반 작업 처리에 사용할 공간을 늘릴 수 있다. 이제 –Xloratio0.1을 새 값으로 사용한다. 적합한 초기 값은 10% 또는 0.1이다.

관리 콘솔에서 –Xloratio를 일반 JVM 인수에 추가하려면 다음 단계를 수행한다.

  1. WebSphere Application Server V6.0에서 Servers - Application Servers - server_name - Java and Process Management - Process definition - Java Virtual Machine - Generic JVM Arguments를 선택한다.

    또는

    WebSphere Application Server V5.0 및 V5.1에서 Servers - Application Servers - server_name - Process Definition - Java Virtual Machine - Generic JVM Arguments를 선택한다.
  2. –Xloratio0.1을 입력하고 이 구성을 저장한 후 서버를 다시 시작한다.

Java SDK 1.4.2를 위한 추가 조정

다중 프로세서

둘 이상의 스레드를 사용하여 GC를 수행할 수 있다. 스레드 수는 시스템의 프로세서 수보다 작아야 한다. 예를 들어, 네 개의 프로세서로 구성된 시스템일 경우 세 개의 스레드를 GC에 사용할 수 있다. 이 값을 얻기 위해 다음 매개변수를 구현한다.

–Xgcthreadsn
네 개의 프로세서로 구성된 시스템에서 세 개의 스레드를 설정하려면 다음 단계를 수행하여 관리 콘솔에서 –Xgcthreads 매개변수를 일반 JVM 인수에 추가한다.

  1. WebSphere Application Server V6.0에서 Servers - Application Servers - server_name - Java and Process Management - Process definition - Java Virtual Machine - Generic JVM Arguments를 선택한다.

    또는

    WebSphere Application Server V5.0 및 V5.1에서 Servers - Application Servers - server_name - Process Definition - Java Virtual Machine - Generic JVM Arguments를 선택한다.
  2. –Xgcthreads3을 입력하고 이 구성을 저장한 후 서버를 다시 시작한다.

SR12 이후

GC 성능을 향상시킬 수 있는 또 하나의 방법은 동시 표시 매개변수를 사용하는 것이다. Verbose GC 출력을 모니터링하여 살펴보았듯이 대부분의 GC 주기의 표시 단계에서 대부분의 시간이 소요된다. 예를 들면, 다음과 같다.

<AF[1640]: Allocation Failure. need 536 bytes, 154266 ms since last AF>
<AF[1640]: managing allocation failure, action=1 (0/879124880) 
(215122200/219781232)>
  <GC(1718): GC cycle started Wed Aug 19 13:16:24 2009
  <GC(1718): heap layout:  (308539208/879124880) (215136552/219781232)  /0>
  <GC(1718): freed 308553560 bytes, 47% free (523675760/1098906112), 
  in 684 ms>
  <GC(1718): mark: 607 ms, sweep: 77 ms, compact: 0 ms>
  <GC(1718): refs: soft 1 (age >= 32), weak 19, final 582, phantom 3>
<AF[1640]: completed in 685 ms>

이 경우에는 총 685밀리초 중 607밀리초가 표시 단계에서 소요되었다. 이 소요 시간을 줄이기 위해 JDK의 SR13 이상 버전에서 올바르게 작동하는 것으로 검증된 다음 매개변수를 사용할 수 있다.

–Xgcpolicy:optavgpause
이 매개변수는 표시 단계에 소요되는 시간을 줄이고 GC 주기가 처리되지 않고 있더라도 표시 단계를 실행 상태로 유지한다.

관리 콘솔(Java SDK 1.4.2의 SR13 이상)에서 –Xgcpolicy:optavgpause 매개변수를 일반 JVM 인수에 추가하려면 다음 단계를 수행한다.

  1. WebSphere Application Server V6.0에서 Servers - Application Servers - server_name - Java and Process Management - Process definition - Java Virtual Machine - Generic JVM Arguments를 선택한다.

    또는

    WebSphere Application Server V5.0 및 V5.1에서 Servers - Application Servers - server_name - Process Definition - Java Virtual Machine - Generic JVM Arguments를 선택한다.
  2. –Xgcpolicy:optavgpause를 입력하고 이 구성을 저장한 후 서버를 다시 시작한다.

결론

지금까지 verbose 가비지 콜렉션을 읽는 방법과 이 도구를 사용하여 andaddress WebSphere Portal 서버 메모리 관련 정보를 분석하는 방법에 대해 살펴보았다.


참고자료

필자소개

Matt Munse는 2002년부터 메모리, 중지, 충돌, 성능을 포함한 WebSphere Portal 런타임 문제와 WebSphere Portal 검색 엔진 문제를 담당하고 있는 Support Engineer이다. WebSphere Portal 서버 성능 문제를 해결하는 지원 업무 외에도 IBM의 특허 관련 업무와 내부용 Java 및 J2EE 애플리케이션 개발 업무도 맡고 있다.


원문 : http://www.ibm.com/developerworks/kr/library/1003_munse/1003_munse.html

Posted by 달콤한녀석

댓글을 달아 주세요

Study...★/Java2011. 7. 4. 00:01

IBM JVM환경에서 발생할 수 있는 Memory Leak에 대한 일반적인 유형에 대해
알아보자.

먼저 GC의 알고리즘을 다시한번 상기시켜 보자.
GC가 Trigging되면, Garbage Collector는 Heap공간 전체를 scan하여
현재 '사용중'이거나 '살아있는'객체들을 표시(mark)한다.
이들을 reachable objects라고 표현하며, 반대로 사용이 끝났거나 reference가
끊긴 객체들을 unreachable objects라고 표현한다.
물론 이들은 GC에 의해 수거될 대상이다.

여기서 reachable objects중, 아래의 경우를 생각해 보자.
A라는 객체가 B라는 객체를 호출하거나 생성하여 reference를 만들었다.
이후, A객체는 아무일을 하지 않더라도 'unreachable objects'가 아닌 'reachable objects'로
분류된다는 점이다.
이러한 관점으로 아래의 일반적인 Memory Leak요소가 될수 있는 사항에 대해
살펴보자.

Hash table
Hash table에 담긴(hashed) 객체들은, 명시적으로 제거되지 않는 한 GC의 대상이 되지 않는다.
hashed object들은 항상 'reachable objects'로 분류되기 때문이다.

Static class
static class data는 일반 객체들과 독립적으로 존재한다.

JNI references
JNI reference는 사용 후, 반드시 명시적으로 제거해야 한다.

Objects with finalizers
finalize 메서드를 가지고 있는 객체들은, Finalizer thread가 기동될때만 GC된다.
하지만, Finalizer thread는 언제 실행될지도 모르며, 또한 한번도 실행되지 않을 수도
있는 특징이 있다. 따라서 특별한 경우가 아니면 Object클래스가 가지는 finalize 메서드를
재정의 하여 사용하지 말도록 한다.



원문 : http://javagosu.tistory.com/5
Posted by 달콤한녀석

댓글을 달아 주세요

Study...★/Java2011. 7. 4. 00:00

앞선 IBM JVM 튜닝 - 2 포스팅에서 AF를 줄이는 방안을 연구해 보자고 했다.

AF란 결국 아래의 두 논리의 경합이다.
1. heap memory상에는 움직일수 없는 객체들이 존재한다. (unmovable objects)
2. heap memory에 객체가 할당되기 위해서는 연속된 memory공간이 필요하다. (contiguous memory block)

여기서 '움직일수 없는 객체(unmovable object)'의 두가지 type에 대해 살펴보도록 하자.

pinned objects

  • java heap 영역이 아닌 space로 부터 참조를 당하고 있는 객체들을 말한다.
    (여기서 java heap 영역이 아닌 space란 말은 native heap, thread stack등의 영역을 의미하는데 이는 포스팅 진행중 설명하겠다.)
  • jvm 내부 스트럭처의 일부분 혹은, jni의 내부의 변수, 혹은 다른 pinned objects등에 의해 reference를 가진 객체를이 해당된다.

dosed objects

  • 순간적으로 pinned objects화 된 객체등을 의미한다.
  • java 코드내의 local variable, 혹은 method 간의 호출에 사용되는 parameter 객체들이 될 수있다.
  • GC Thread가 돌때, 위에서 설명한 dosed object들은 active로 간주되어 GC의 대상에서 벗어나게 되고,이후 GC Thread에 의해서 reference 참조 여부가 결정된 후, 일반 객체처럼 수거된다.

아래의 그림을 보면 쉽게 이해가 갈 것이다.

이러한 unmovable objects들 중, 다행히 dosed object들은 생명이 짧다. 따라서 곧 mark-sweep될 가능성이 많다.
하지만, 문제는 pinned object들 이다. 이 녀석들은 대부분 긴 생명력을 자랑하면서, 제한된 Heap 공간에 자기 멋대로 자리를 틀어 버리기 때문이다.
필연적으로 이러한 pinned objects들이 다수 존재하게 되면, 그만큼 AF가 발생할 확률이 높다는 말이 된다.

그렇다면, 어떠한 방법이 있을까?

사례 1) Heap사용률은 높지 않지만, 다수의 pinned object에 의해 AF가 발생.
이경우는, pinned objects들만 사용할 수 있는 전용공간을 Heap상에 만들어 주면 된다.
이때 사용되는 대표적인 옵션은 아래와 같다.
-Xknnn  -Xpiii[k][,ooo[k]] 

  • nnn is the maximum number of classes used by the application,
  • iii is the size of the primary pinned cluster, 
  • ooo is the size of the overflow pinned clusters in bytes, and
  • Using k changes value from bytes to kilobytes.

윗 영문해설은 'ibm'사이트에서 발췌한 항목에 대한 설명인데, 개인적으로는 다음과 같이 이해하고 있다.
 'nnn'은 메모리에 로딩된 application class의 총 개수를 의미하며, 'iii'는 pinned objects를 연속된 공간에 묶기 위한 cluster된 공간의 크기인데, WAS등이 부팅되면서 로딩시키는 class들 중, pinned성격의 object들이 먼저 위치하는 공간의 크기를 의미하며, 'ooo'는 JVM Runtime시 종종 생성되고 사라지는 pinned object들이 위치하는 공간이다.
통상, -Xk로 표현되는 옵션을 'KCluster'라고 부르며, -Xp로 표현되는 옵션을 'PCluster'라고 부른다.

통상적인 경우, 1.3.1_07 이상 및 1.4.2 이상의 ibm jdk에서는 이를 산출하기 위한 back data를 볼 수 있는 옵션을 제공하고 있다.

  • 1.3.1_07 이상의 1.3대 jvm
    -verbosegc -Xtgc2
  • 1.4.2 이상의 jvm
    -verbosegc -Dibm.dg.trc.print=st_verify

위의 설정이 작동하게 되면, standard out 에 아래와 같은 로그가 찍히게 된다.
<GC(VFY-SUM): pinned=3000(classes=2755/freeclasses=0) dosed=9388 movable=1045582 free=3340>
해석해 보면, 총 2755개의 application class들이 로딩되어 있으며, 이중 unmovable object로는 pinned objects가 3000개, 그리고 순간 pinned화 된 dosed object가 9388개 존재한다. 기타 movable한 object는 1045582개 존재하며, mark가 끊긴 object들은 3340개 존재한다.

위와같은 로그를 획득하였다면, -Xk와 -Xp의 sizing을 해 보자.

  • -Xk sizing
    통상적으로 로딩된 class개수의 10%정도를 더 설정해 주는 것을 권고한다. 위의 data를 기반으로 산출해 보면 아래와 같다.
    2755 + (2755x0.1) = 3030, 따라서 -Xk3030과 같이 설정한다.
  • -Xp sizing
    이부분에 대한 명쾌한 설명을 하고 있는 자료를 본적이 없다. IBM에서도 아래와 같이 설명하고 있다.
    If the problem still persist after setting a -Xk value then you may want to look at setting  -Xp as well and examining the application code to see if you can reduce the size of the larger objects that are being requested.
    Sizing the -Xp option is a complex task and should only be done with assistance from IBM Support.


    위에서 설명한데로, -Xpiii[k][,ooo[k]]형식이 되는데, 'iii'는 pinned objects를 연속된 공간에 묶기 위한 cluster된 공간의 크기인데, WAS등이 부팅되면서 로딩시키는 class들 중, pinned성격의 object들이 먼저 위치하는 공간의 크기를 의미하며, 'ooo'는 JVM Runtime시 종종 생성되고 사라지는 pinned object들이 위치하는 공간으로 이해한다.

    따라서, -Xk옵션으로 별다른 개선효과가 없다면, AF가 발생했을 당시의 gc로그를 기반으로, AF를 유발한 object 크기를 유형별로 산출하여, 단위시간에 몰리는 object크기의 총 합정도를 설정하여, 반복테스트를 통하여 가장 좋은 성능을 발휘하는 임계치를 찾는 방법을 사용해야 할 것 같다.

사례 2) unmovable obejcts는 많지 않지만, 다수의 dosed objects들에 의한 AF발생.

  • -Xcompactgc
    모든 GC사이클 수행시마다, compact를 수행한다. 성능은 크게 감소할 것을 감수해야 한다.
    하지만, 해당 옵션을 활성화 시켜서 AF가 많이 줄어 든다고 판단되면, dosed objects들에 의한 AF가 많다라고 간주하는데 판단기준이 될 수 있다.
  • -Xpartialcompatgc
    compact trigger가 자주 발생한다. 즉, 기존의 full compaction을 점진적(incremental)으로 진행한다.
    비활성화는 -Xnopartialcompactgc로 설정하면 되고, full compaction 모드로 작동하게 된다.
  • -Xgcpolicy
    IBM JVM 튜닝 - 1 을 참조한다.

사례 3) unmovable obejcts는 많지 않지만, 다수의 large size objects들에 의한 AF발생.
large object를 위한 loa(large object area)영역을 지정한다.

  • jdk 1.4 이상
    -Xloratio : loa 영역의 크기를 백분률로 지정한다. 
                   loa 영역을 지정한 경우, 통상적으로 Xmx영역을 일정비율 늘려줘야 한다. 
                   공식은 아래와 같다.               
                                       New Xmx = Current Xmx / (1 - loratio)
  • jdk 1.5이상
    -Xloa : 64k 이상의 large object들만을 담는 loa(large object area)를 활성화 한다.
    -Xloainitial : loa영역의 초기 백분률로 0~0.95의 수치를 지정한다. 기본값은 0.05(5%)이다.
    -Xloamaximum : loa영역의 최대 백분률로 0~0.95의 수치를 지정한다. 기본값은 0.5(50%)이다.



포스팅을 마무리하고 보니, IBM JVM 튜닝중 AF쪽에 포커스가 맞추어 진 느낌이다.
다음에는 IBM JVM 전반에 걸쳐 포스팅을 해볼까 한다.


원문 : http://javagosu.tistory.com/5

'Study...★ > Java' 카테고리의 다른 글

IBM JVM 튜닝 - 4  (0) 2011.07.04
IBM JVM 튜닝 - 3  (0) 2011.07.04
IBM JVM 튜닝 - 2  (0) 2011.07.03
IBM JVM 튜닝 - 1  (2) 2011.07.03
Posted by 달콤한녀석

댓글을 달아 주세요

Study...★/Java2011. 7. 3. 23:59

IBM JVM 튜닝 - 1 편에서도 살펴 보았지만, IBM JDK는 근본적으로 Single Space Heap 구조..
즉, '통짜Heap'구조를 가진다.
이러한 특징으로 인해 필연적으로 안을 수 밖에 없는 문제가 바로 '메모리 단편화(Memory Fragmentation)'현상이다.

아래 그림을 보자.


단일 객체는 쪼개져서 메모리 공간에 존재할 수 없다.
즉, 연속된 공간(Contiguous memory block)에서만 존재 할 수 있다는 이야기가 된다.

이렇게, 객체의 메모리 할당이 실패하게 되는 현상을 Allocation failure(이하 AF)라고 부른다.
그렇다면, AF가 발생했을때 IBM-JVM은 어떤 작업을 수행할까?
바로 Compaction 이란 단계를 수행한다.

아래 그림을 보자.

즉, 뿔뿔히 흩어져 있는 Live Object들을 한쪽 공간으로 쭉 밀어내어, 가용한 연속된 Heap공간을 확보하는 작업이다.
(compact가 계속되면, Heap영역은 Full이 나는 것인가? compact의 빠른 이해를 돕기위해 윗 그림에서는 건너 뛰었지만, 그림의 중간중간에 mark-sweep이라고 하는 GC가 필요시마다 계속 발생하면서, reference가 끊긴 객체들을 지속적으로 수거하면서 available한 공간확보를 지속한다는 점을 잊진 말자.)

문제는, 이 Compaction이란 작업이 매우 무거운 작업에 속한다는 점이다.
따라서, Compaction의 발생빈도에 비례하여 시스템의 Performance는 저하될 수 밖에 없다.

썰이 길었고, 이제 이 Compaction의 횟수를 줄이는 방안에 대해 고민해 보자.
Compaction은 JVM에 의해 필요에 의해 발생하기도 하고, 명시적인 옵션(나중에 설명하겠다)에 의해서도 일부
제어가 가능하지만, 대부분 AF가 발생하면 실행되는 것이 일반적이다.
따라서, AF를 최대한 줄일 수 있는 방법을 먼저 고민해 보자.

간만의 포스팅이라서... 힘들다..
다음편에 계속...


원문 : http://javagosu.tistory.com/5

'Study...★ > Java' 카테고리의 다른 글

IBM JVM 튜닝 - 3  (0) 2011.07.04
IBM JVM 튜닝 - 2  (0) 2011.07.03
IBM JVM 튜닝 - 1  (2) 2011.07.03
java GC 관련  (0) 2011.06.16
Posted by 달콤한녀석

댓글을 달아 주세요

Study...★/Java2011. 7. 3. 23:57

IBM JVM 튜닝 - 1

JVM 구조

IBM JVM 구성하는, 각각의 Component structure 아래와 같이 나뉜다.

 

영역의 주요 기능은 아래와 같이 요약된다.

 

구분

기능

JVM API

JVM External program 사이의 상호작용에 관여

Diagnostics

JVM 기능에 편리성과 유용성(RAS) 제공

Memory

management

Java application 의한 System memory 효율적인 사용에 관여함

Class loader

Java code 동적 로딩의 편리성 제공

Interpreter

Stack-base bytecode 해석에 관여함

Platform

port layer

다양한 운영시스템에서 JVM native function 사용할 있도록 하는 기능제공

[ 1] IBM JVM 구성 요소 설명

 

 

여기서 우리는 ‘Memory management’ 중점적으로 다뤄본다.


JIT 컴파일러

흔히, IBM JVM JIT계열의 JVM이라고 표현한다.

JIT 흔히 Just-In-Time 약자로 알려져 있으며, 이는 JVM part라기 보다는, SDK 기본 구성요소로 생각하는 것이 맞다.

 

Java Interpreter 언어이고, 이는 소스가 bytecode 컴파일 되고, 실행되기 위해서는 다시금 system code 해석되어 수행되어야 하는, performance적인 저하요소를 극복하기 위해 자주 수행되는 Java method 대상으로 미리 system code 해석해서, Method call되면 컴파일 과정 없이 바로 서비스를 하는 방식으로 작동한다.

 

 이런 JIT 컴파일러가 때때로 Runtime 문제점이 발생하는 경우는, 아래의 방법으로 JIT 옵션을 꺼둘 수도 있다.

 

구분

설명

Unix 환경변수 제어방법

Korn : export JAVA_COMPILER=NONE

Bourne : JAVA_COMPILER=NONE

export JAVA_COMPILER

C : setenv JAVA_COMPILER NONE

JVM Option 1

-Djava.compiler=NONE

JVM Option 2

-Xint

[ 2] JIT 컴파일러 비활성화

 

 

, 아래와 같이 JIT 옵션을 수도 있다.

 

구분

설명

Unix 환경변수 제어방법

Korn : exprt JAVA_COMPILER=jitc

Bourne : JAVA_COMPILER=jitc

export JAVA_COMPILER

C : setenv JAVA_COMPILER jitc

JVM Option 1

-Djava.compiler=jitc

JVM Option 2

-Xjit

[ 3] JIT 컴파일러 활성화


Garbage Collector

Sun HotSpot 계열의 JVM ‘New/Old/Permanent’등의 세대(Generation)’ 불리는 영역으로 분리된 Heap구조를 가진다.

이에 반해, IBM JVM 영역이 따로 분리되지 않은 하나의 ‘Single Space’ Heap 구성되어 있다.

 

heapbase

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

heaplimit

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

heaptop

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

참고로, IBM JDK 1.5부터는 아래와 같이 세대(Generation)’기반의 Heap 구조를 지원한다.

(GC 알고리즘이 Concurrent Generational Collector 경우의 Heap 구조임)


  

영역이 어떤 식으로 Garbage Collector 의해 사용되는지 설명하기 위해서,

‘Generational Concurrent Garbage Collection’ 알고리즘에 대해 잠깐 언급하도록 한다.

 

JVM Logic 처리하는 동안, 새로운 Object들은 당연히 ‘Nursery’영역에 생기게 된다. 만일, 새로운 Object 할당되는데 필요한 연속된 메모리 영역 부족하게 되면, 객체는 ‘Tenured’영역으로 옮겨지게 된다. 또한, Garbage collection 발생시 옮겨지기도 한다.

 

Nursery 영역은 ‘Allocate Space’ ‘Survivor Space’ 나뉘게 된다.

Object 최초 Allocate Space 생기게 된다. 만일, Space 부족하게 되는 경우,

Allocation Failure 발생되면 Garbage Collector 작동되고, Scavenge 시작된다.

Scavenge 진행되는 동안, reference 살아있는 Object들은 ‘Survivor Space’ 이동되고, 이때 reference 없는 Object들은 건들지 않는다.

Reference 살아있는 Object들의 이동작업이 끝나게 되면, ‘Allocate Space’ ‘Survivor Space’ 역할을 순간적을 바꾸게 된다.

 

이때, 기존의 reference 없는 Object들은 순간적으로 비워지게 된다. 그리고, 다음 Scavenge 발생할 까지는 ‘Survivor Space’ Object 위한 Allocate 공간 업무를 수행하게 된다.

 


JVM 주요 옵션 소개

GC command-line options

-verbose:gc

garbage collection 정보를 standard out 으로 출력한다.

 

-Xverbosegclog:<file, X, Y>

garbage collection 정보를 파일로 출력한다. 만약 integer X Y 값을 명시하면 output Y GC Cycle output 포함하는 X 파일로 재지정된다.

) -Xverbosegclog:/user/logs/gclog/gclog.log //로그 경로 설정

 

-Xgcpolicy: <optthruput | optavgpause | gencon | subpool>

option garbage collector 행동을 제어한다.

-. optthruput

concurrent mark 비활성화 한다. 만약 application response time 문제가 없다면 option 사용하여 최적의 throughput 있다. Optthruput default 값이다.

-. optavgpause

concurrent mark 활성화 한다. 만약 일반적인 garbage collections 의해 application response time 문제가 있다면 option 사용함으로 문제를 줄일 있다.

-. gencon

Concurrent generational GC 겸용하여 사용함으로 garbage collection 지체 시간을 최소화 있다.

-. subpool

concurrent mark 비활성화 한다. 이것은 heap 객체들을 배치할 나은 성능을 내기 위해 향상된 object allocation 알고리즘을 사용한다. option 16 이상의 processor SMP system에서 실행되며, subpool option AIX, Linux PPC zSeries, z/OS, i5/OS 에서 가능하다.

 

-Xmx<value>

최대 heap size 지정한다. (Xmx >= Xms)

) -Xmx256m // 최대 heap size 256mb 지정한다.


-Xms<value>

최소 heap size 지정한다.  Xmo 또한 사용할 있다. 최소 size 8KB이다.

scavenger 활성화 되어 있을 경우, -Xms >= -Xmn + -Xmo

scavenger 비활성화 되어 있을 경우, -Xms >= -Xmo

) -Xms256m // 최소 heap size 256mb 지정한다.


-Xcompactgc

모든 garbage collections(system 또는 global) 대하여 압축을 가능하게 한다.


-Xnocompactexplicitgc

System.gc() 호출에 의한 압축을 불가능하게 한다. 압축은 만약 –Xcompactgc 명시하거나 또는 compaction triggers 만나면 global garbage collections 에서 발생한다.


-Xcompactexplicitgc          

System.gc() 호출 때마다 모든 GC 시스템에서 압축을 사용 가능하게 한다.


-Xnocompactgc

모든 garbage collections(system 또는 global) 대하여 압축을 사용 불가능하게 한다.


-Xnoclassgc

Class garbage collection 비활성화 한다. JVM 의해서 이상 사용되지 않는 Java class 들과 연관된 storage garbage collection 끈다. dynamic 클래스 로드 해제를 사용 불가능하게 한다.


-Xclassgc

dynamic 클래스 로드 해제를 사용 가능하게 한다.


-Xalwaysclassgc

global collection 동안 항상 dynamic class load 해제를 수행한다. Default -Xclassgc 의해 정의된다.

 

-Xmaxf<percentage>

garbage collection free 되어야 하는 heap 최대 percentage 지정한다. 만약 free 영역이 값을 초과하면 JVM heap 줄이기 위해 시도한다. Default 0.6(60%) 이다.


-Xminf<percentage>

garbage collection이후 free되어야 하는 heap 최소 percentage 지정한다. 만약 free영역 값에 미치는 경우 JVM heap 확장하기 위해 시도한다. Default 30%이다.


-Xgcthreads<number>

Garbage Collector thread 수를 지정한다. Default 물리적인 CPU 수로 지정된다. 다른 수로 지정하기 위해 (예를 들어 4)  -Xgcthreads4 표기한다.

 

Nonstandard command-line options

-Xss<size>

모든 Java thread 최대 stack size 지정한다. Default 32bit JVM에서 256KB, 64bit JVM에서 512KB 이다.


-Xmso<size>

OS thread stack size 지정한다.  

JIT command-line options

-Xint

JVM JIT 사용불가하고, Interpreter 로만 사용한다.


-Xquickstart

최적화를 지연하여 시작 시간을 향상시킨다. 


 분석 기술

GC 알고리즘의 이해

IBM JDK에서는 아래와 같이 주요 4가지 Garbage Collection 옵션을 제공한다.

이들은 아래와 같은 방법으로 설정이 가능하다.

-Xgcpolicy

여기에 설정할 있는 옵션은 다음과 같다.

optthruput GC 알고리즘 설명

구분

설명

옵션

-Xgcpolicy:optthruput

설명

옵션은 default GC 알고리즘 이다.

특징으로는, 작동 일시적으로 정지하는 현상이 발생한다는 점이다.

Object할당을 시도할 , Allocation Failure 발생하게 되면, Garbage Collector reference 끊긴 Object 수집하여 삭제하게 된다.

이때, 필연적으로 JVM Lock 걸리면서 멈추는 현상이 발생하게 된다.

Application 복잡해지고, 그에 따라 Heap 커지게 되면, 역시 GC발생시 멈추게 되는 시간도 증가하게 된다.

장점

Throughput 향상될 있다.
(General GC, Disable concurrent mark)

단점

작동 일시적으로 정지하는 현상이 발생한다.

 

optavgpause GC 알고리즘 설명

구분

설명

옵션

-Xgcpolicy:optavgpause

설명

위에서 설명한 ‘optthruput’ GC 알고리즘의 단점인 ‘JVM 정지시간 보완하기 위한 GC 알고리즘 하나이다.

이는, Application 수행 , Garbage Collection 위한 Thread 추가적으로 생성하고 기동시켜서, reference 끊긴 Object들에 대한 scavenge 작업을 수행시켜서, 실제 Garbage Collector 수행될 , 전체 Heap영역에 대한 Object선별작업을 수행할 필요 없이 reference 끊긴 Object들만을 수거해 있도록 돕는다.

장점

전반적인 응답속도(Response Time) 향상하는 효과를 가져올 있다.

(Enables concurrent mark)

단점

Concurrent Thread 기동에 의한, 실제 Application 수행에 있어서의

Throughput 감소한다.

 

gencon GC 알고리즘 설명

구분

설명

옵션

-Xgcpolicy:gencon

설명

해당 옵션이 설정되면, JVM 할당된 Heap 세대(Generation)’기준으로 분류한다. 이는 위에서 살펴보았듯이, ‘Nursery Space’ ‘Tenured Space’ 말한다.

JVM Logic 처리하는 동안, 새로운 Object들은 당연히 Nursery’영역에 생기게 된다. 만일, 새로운 Object 할당되는데 필요한 연속된 메모리 영역이

부족하게 되면 객체는 Tenured 영역으로 옮겨지게 된다.

또한, Garbage collection 발생시 옮겨지기도 한다.

Nursery 영역은 Allocate Space’와 Survivor Space 나뉘게 된다.

Object 최초 Allocate Space 생기게 된다. 만일, Space 부족하게 되는 경우, Allocation Failure 발생되면, Garbage Collector 작동되고, Scavenge 시작된다.

Scavenge 진행되는 동안 reference 살아있는 Object들은 Survivor Space 이동되고, 이때 reference 없는 Object들은 건들지 않는다.

Reference 살아있는 Object들의 이동작업이 끝나게 되면, Allocate Space Survivor Space 역할을 순간적을 바꾸게 된다.

이때, 기존의 reference 없는 Object들은 순간적으로 비워지게 된다. 그리고 다음 Scavenge 발생할 까지는 Survivor Space Object 위한 Allocate 공간 업무를 수행하게 된다.

장점

전반적인 응답속도(Response Time), Throughput 동시에 평균적으로 향상하는 효과를 가져올 있다.
(Enable concurrent mark + General GC)

단점

CPU overhead 상대적으로 발생할 있다.

 

subpool GC 알고리즘 설명

구분

설명

옵션

-Xgcpolicy:subpool

설명

Heap 공간을 다수의 sub pool 할당하여 Object 관리하는 기법이다.

여기에 LOA(Large Object Area) SOA(Small Object Area) 개념이 들어간다.

장점

상대적으로 높은 성능을 발휘한다.

단점

16 CPU 이상의 사양 서버 환경에서 사용해야 한다.

또한, AIX, z/OS, Linux PPC 특정 플랫폼에서만 사용할 있다.

 

GC Dump 이해

앞에서, GC 알고리즘에 대해 개략적으로 살펴보았다.

여기서는, 로그가 실제 어떤 식으로 생성되는지 간략한 예를 살펴보도록 한다.

아래는, 실제로 JEUS 각각의 GC 알고리즘을 적용시켜 생성한 Dump이다.

 

–Xgcpolicy:optthruput GC dump

<af type="tenured" id="4" timestamp="  2 28 10:16:42 2008" intervalms="432.499">

  <minimum requested_bytes="33562648" />

  <time exclusiveaccessms="0.140" />

  <tenured freebytes="158830512" totalbytes="536870912" percent="29" >

    <soa freebytes="136268104" totalbytes="493921280" percent="27" />

    <loa freebytes="22562408" totalbytes="42949632" percent="52" />

  </tenured>

  <gc type="global" id="5" totalid="5" intervalms="434.640">

    <compaction movecount="450409" movebytes="69221728" reason="heap fragmented" />

    <refs_cleared soft="0" threshold="32" weak="0" phantom="0" />

    <finalization objectsqueued="0" />

    <timesms mark="72.584" sweep="5.045" compact="130.030" total="207.766" />

    <tenured freebytes="340455528" totalbytes="536870912" percent="63" >

      <soa freebytes="292138088" totalbytes="488553472" percent="59" />

      <loa freebytes="48317440" totalbytes="48317440" percent="100" />

    </tenured>

  </gc>

  <tenured freebytes="306892880" totalbytes="536870912" percent="57" >

    <soa freebytes="258575440" totalbytes="488553472" percent="52" />

    <loa freebytes="48317440" totalbytes="48317440" percent="100" />

  </tenured>

  <time totalms="208.154" />

</af>

로그 패턴을 보면, Allocation Failure 발생하였고, GC 거쳐 Tenured영역의 Free Space 57% 증가했음을 있다. 

–Xgcpolicy:optavgpause GC dump

<af type="tenured" id="40" timestamp="  2 28 10:17:02 2008" intervalms="223.402">

  <minimum requested_bytes="37748760" />

  <time exclusiveaccessms="36.573" />

  <tenured freebytes="28931592" totalbytes="1073741824" percent="2" >

    <soa freebytes="28931592" totalbytes="1073741824" percent="2" />

    <loa freebytes="0" totalbytes="0" percent="0" />

  </tenured>

  <gc type="global" id="42" totalid="42" intervalms="223.577">

    <refs_cleared soft="0" threshold="32" weak="0" phantom="0" />

    <finalization objectsqueued="0" />

    <timesms mark="28.562" sweep="3.428" compact="0.000" total="32.092" />

    <tenured freebytes="211487536" totalbytes="1073741824" percent="19" >

      <soa freebytes="211487536" totalbytes="1073741824" percent="19" />

      <loa freebytes="0" totalbytes="0" percent="0" />

    </tenured>

  </gc>

  <tenured freebytes="173738776" totalbytes="1073741824" percent="16" >

    <soa freebytes="173738776" totalbytes="1073741824" percent="16" />

    <loa freebytes="0" totalbytes="0" percent="0" />

  </tenured>

  <time totalms="68.845" />

</af>

 
–Xgcpolicy:gencon GC dump

<af type="tenured" id="154" timestamp="  2 29 09:57:50 2008" intervalms="452.265">

  <minimum requested_bytes="37748760" />

  <time exclusiveaccessms="2.137" />

  <nursery freebytes="33161216" totalbytes="33554432" percent="98" />

  <tenured freebytes="242872304" totalbytes="1006632960" percent="24" >

    <soa freebytes="211147296" totalbytes="956301312" percent="22" />

    <loa freebytes="31725008" totalbytes="50331648" percent="63" />

  </tenured>

  <gc type="global" id="226" totalid="1071" intervalms="452.406">

    <refs_cleared soft="0" threshold="32" weak="0" phantom="0" />

    <finalization objectsqueued="8" />

    <timesms mark="26.053" sweep="3.163" compact="0.000" total="29.278" />

    <nursery freebytes="33494840" totalbytes="33554432" percent="99" />

    <tenured freebytes="470984032" totalbytes="1006632960" percent="46" >

      <soa freebytes="439259024" totalbytes="946235392" percent="46" />

      <loa freebytes="31725008" totalbytes="60397568" percent="52" />

    </tenured>

  </gc>

  <nursery freebytes="33494840" totalbytes="33554432" percent="99" />

  <tenured freebytes="433235272" totalbytes="1006632960" percent="43" >

    <soa freebytes="401510264" totalbytes="946235392" percent="42" />

    <loa freebytes="31725008" totalbytes="60397568" percent="52" />

  </tenured>

  <time totalms="31.585" />

</af>

 

<af type="nursery" id="881" timestamp="  2 29 09:57:50 2008" intervalms="285.580">

  <minimum requested_bytes="37748760" />

  <time exclusiveaccessms="0.110" />

  <nursery freebytes="31100848" totalbytes="33554432" percent="92" />

  <tenured freebytes="433235272" totalbytes="1006632960" percent="43" >

    <soa freebytes="401510264" totalbytes="946235392" percent="42" />

    <loa freebytes="31725008" totalbytes="60397568" percent="52" />

  </tenured>

  <gc type="scavenger" id="846" totalid="1072" intervalms="285.732">

    <flipped objectcount="3460" bytes="171648" />

    <tenured objectcount="0" bytes="0" />

    <refs_cleared soft="0" weak="0" phantom="0" />

    <finalization objectsqueued="0" />

    <scavenger tiltratio="50" />

    <nursery freebytes="33013736" totalbytes="33554432" percent="98" tenureage="3" />

    <tenured freebytes="433235272" totalbytes="1006632960" percent="43" >

      <soa freebytes="401510264" totalbytes="946235392" percent="42" />

      <loa freebytes="31725008" totalbytes="60397568" percent="52" />

    </tenured>

    <time totalms="3.648" />

  </gc>

  <nursery freebytes="33013736" totalbytes="33554432" percent="98" />

  <tenured freebytes="433235272" totalbytes="1006632960" percent="43" >

    <soa freebytes="401510264" totalbytes="946235392" percent="42" />

    <loa freebytes="31725008" totalbytes="60397568" percent="52" />

  </tenured>

  <time totalms="3.923" />

</af>

  

–Xgcpolicy:subpool GC dump

<sys id="1" timestamp="  2 29 10:03:16 2008" intervalms="0.000">

  <time exclusiveaccessms="0.048" />

  <tenured freebytes="373520640" totalbytes="536870912" percent="69" />

  <gc type="global" id="1" totalid="1" intervalms="0.000">

    <classloadersunloaded count="0" timetakenms="0.973" />

    <refs_cleared soft="73" threshold="32" weak="127" phantom="4" />

    <finalization objectsqueued="21" />

    <timesms mark="56.218" sweep="5.343" compact="0.000" total="62.748" />

    <tenured freebytes="491131504" totalbytes="536870912" percent="91" />

  </gc>

  <tenured freebytes="491131504" totalbytes="536870912" percent="91" />

  <time totalms="63.282" />

</sys>

 

Subpool CPU 16 이상인 환경에서 최적화 되어있다고 앞서 말했다.

종종 System Capacity 부족한 환경에서는 아래와 같은 로그가 목격되기도 한다.

Module=/usr/java5_64/jre/bin/libj9gc23.so

Module_base_address=0900000001046000

Target=2_30_20071004_14218_BHdSMr (AIX 5.3)

CPU=ppc64 (4 logical CPUs) (0x1f0000000 RAM)

 

위의 로그와 비슷하게, System.gc() 명시적으로 호출된 경우는 아래와 같은 GC Dump 발생한다.

<sys id="1" timestamp="  2 29 10:03:16 2008" intervalms="0.000">

  <time exclusiveaccessms="0.048" />

  <tenured freebytes="373520640" totalbytes="536870912" percent="69" />

  <gc type="global" id="1" totalid="1" intervalms="0.000">

    <classloadersunloaded count="0" timetakenms="0.973" />

    <refs_cleared soft="73" threshold="32" weak="127" phantom="4" />

    <finalization objectsqueued="21" />

    <timesms mark="56.218" sweep="5.343" compact="0.000" total="62.748" />

    <tenured freebytes="491131504" totalbytes="536870912" percent="91" />

  </gc>

  <tenured freebytes="491131504" totalbytes="536870912" percent="91" />

  <time totalms="63.282" />

</sys>


Java Thread Dump 분석

Java Thread Dump, 특정 Java Process 대한 청사진이라 해석될 있다.

IBM 플랫폼에서 Java Thread Dump text형태로 생성된다.

이를, 직접 열어서 내용을 Trace하는 것도 가능하지만, 여기서는 Visual Tool 이용한 분석법을 소개한다.

 

JCA 이용한 Java Thread Dump 분석

1. 다운로드 : http://www.alphaworks.ibm.com/tech/jca (파일명:jca*.zip)

2. 실행화면

 

 3. 설명

실제 javacore덤프를 분석한 화면이다.

덤프 생성 당시, 가용한 메모리가 없었다는 경고와 함께, Worker Thread 하나가

Running 상태였다는 정보를 쉽게 있다.

이와 같이, Worker Thread 상태정보 Heap Memory Usage정보, Thread Monitor 상태정보(dead lock)등의 정보에 쉽게 접근이 가능하다.


Java Heap Dump 분석

Java Heap Dump, 특정 Java Process allocation 되었던 Heap Memory 대한 청사진이라 있다.

IBM 플랫폼에서는 text형태, 혹은 phd(Portable Heap Dump)포맷으로 생성된다.

Heap Dump 분석에는 주로 아래와 같은 방법이 사용된다.

구분

설명

URL

Text 기반

HeapRoots (HR*.jar)

http://www.alphaworks.ibm.com/tech/heaproots/download

Svcdump (svcdump.jar)

http://www-1.ibm.com/support/docview.wss?rs=180&uid=swg21190476

GUI 기반

HeapAnalyzer (ha*.jar)

http://www.alphaworks.ibm.com/tech/heapanalyzer/download

 

여기서는 GUI기반의 HeapAnalyzer 소개한다.

HeapAnalyzer 이용한 Java Heap Dump 분석

1. 실행화면 


2.
설명

실제 Heap Dump 분석한 화면이다.

Heap Dump 생성 당시의 Memory allocation 대한 Stack정보를 계층구조로 보여주고 있어서, Memory 누수 라던지 OOM(Out Of Memory)상황이 발생하였을 경우, 원인파악에 매우 도움이 되는 화면을 제공한다.

(*주의: Heap Dump Size 매우 경우는, 서버의 X-Window환경에서 작업하도록 한다. 통상적인 Heap Dump 분석에는 많은 Memory 필요하기 때문이다.)


GC Dump 분석

GC Dump 분석이란, -verbose:gc –Xverbosegelog:logname.log 결과로 생성된 GC log파일을 분석하는 것을 말한다.

역시, script 이용하는 방법과 command-line 이용한 명령어 사용방법 등이 있는데, 여기서는 역시 GUI 기반의 툴인 ‘GCCollector’ 이용하는 방법을 소개한다.

 

GCCollector 이용한 GC Dump 분석

1. 다운로드: GCCollector 실행하기 위해서는 JFreeChart 다운받아야 한다.           

구분

URL

GCCollector

http://www.alphaworks.ibm.com/tech/gcdiag/download (파일:GCCollector.zip)

JFreeChart

http://www.jfree.org/jfreechart/index.html

 

2. GCCollector 실행파일에 오류가 발생할 경우 아래와 같이 작성한다.

javaw -Xmx300m –classpath lib/GCCollector.jar;lib/jfreechart-1.0.0-rc1.jar;lib/jcommon-1.0.0-rc1.jar it.imperato.jvmperf.GCCollector

3. 실행화면

 

4. 설명

실제 GC Dump 분석한 화면이다. (-Xgcpolicy:optthruput or –Xgcpolicy:optavgpause)

GCCollector 통해 판단할 있는 항목은 아래와 같다.

l     GC Interval

l     GC Duration (Mark, Sweep, Compact, Total)

l     Allocation Failure: 실제 Garbage Collector 작동된 count 같다고 생각하면 된다.


이럴 이렇게

표준 설정 옵션

표준 옵션

-Xms512m -Xmx1024m

-verbose:gc   

-Xverbosegclog:/user/logs/gclog/gclog.log

전체적인 GC Time 너무 길고, Response Time 너무 나오지 않습니다.

상황

GC 수행시간 그래프를 보면, 수행시간이 오래 걸리는 GC들의 peak 자주 목격됩니다.

Response Time 역시 너무 나옵니다.

조치

대부분, GC 있어서 Full heap collection 혹은 compaction 소요되는 시간이 너무 경우 발생할 있습니다.

경우, -Xgcpolicy:optavgpause 옵션을 적용하면, concurrent 하게 heap collection 발생하게 되고, GC 따른 pause시간이 감소하여, 전체적인 Response Time 향상을 기대할 있습니다.

적용 옵션

-Xgcpolicy:optavgpause

Throughput 너무 적게 나옵니다.

상황

CPU Memory등의 capacity 좋은 장비임에도 불구하고, WAS 서비스의 전체적인

Throughput 너무 나오지 않습니다.

조치

경우, -Xgcpolicy:optthruput 옵션을 적용하면, concurrent mark&sweep 작업을 막음으로써, 대부분의 Thread Business Service 수행하는데 사용되도록 유도하여 전체적인 Throughput 향상시키는데 도움이 있습니다.

만일, CPU 16 이상인 사양 환경의 경우 –Xgcpolicy:subpool 옵션이 좀더 효과적인 성능을 발휘 있습니다.

 

적용 옵션

일반적인 경우 : -Xgcpolicy:optthruput

16 이상의 CPU 환경 : -Xgcpolicy:subpool

Garbage Collection 너무 자주 발생합니다.

상황

GC Interval 매우 좁게 나타나며, GC count 너무 높게 나옵니다.

조치

Application 특성에 비해 Heap Size 너무 작게 설정되어 있을 있습니다.

또한, 경우 –Xgcpolicy:optthruput 옵션이 도움이 있습니다.

적용 옵션

-Xmx 늘림

-Xgcpolicy:optthruput

설정된 Heap Size 실제 사용량의 차이가 너무 심하게 납니다.

상황

실제 WAS JVM 할당한 Heap Size 사용되는 Heap Size 등락폭이 너무 심하게 자주 바뀝니다.

조치

Heap Size 너무 크게 설정되어 있을 있습니다.

Heap Size 줄이고, Generation Heap Space 설정된 경우 ‘Nursery’영역의 Size 좀더

할당해 주는 것도 도움이 있습니다.

적용 옵션

-Xmx 줄임

-Xgcpolicy:optthruput

CPU 16 이상의 환경에서 WAS 운영하는 경우, 권장 GC 정책은 무엇인가요?

상황

CPU 16 이상의 AIX장비의 IBM JDK 1.5 이상 환경에서 WAS 운영하고자 합니다.

권장 GC 정책은 무엇 인가요.

조치

경우 -Xgcpolicy:subpool 옵션을 권장합니다.

하지만 Business Application 성격에 따라 다른 결과가 나올 있음으로, 다른 GC 정책과의 비교 Test 필요합니다.

적용 옵션

-Xgcpolicy:subpool

 Heap Size 넉넉하게 설정하였음에도 불구하고, Allocation Failure 자주 발생합니다.

상황

Heap Size 넉넉하게 설정하였습니다. Application에서 사용하는 Object들도 매우 경우는 별로 발견되지 않는데, 잦은 AF(Allocation Failure) 발생하고 있습니다.

조치

메모리 단편화(Memory Fragmentation) 의심해 있습니다.
WAS
JVM -Dibm.dg.trc.print=st_verify 설정하여, kCluster/pCluster 설정이 필요합니다. 또한, -Xloratio옵션을 주어 LOA 영역에 대한 사이즈 조절도 때때로 유효한 경우가 있습니다.

적용 옵션

-Xk –Xp 설정 (-Dibm.dg.trc.print=st_verify 설정 , 로그 분석을 통한 Size 설정)
stdout 로그에 verbosegc정보에 pinned=xxx 라는 형식으로정 보가 남게된다.

-Xloratio 설정


원문 : http://javagosu.tistory.com/5

'Study...★ > Java' 카테고리의 다른 글

IBM JVM 튜닝 - 2  (0) 2011.07.03
IBM JVM 튜닝 - 1  (2) 2011.07.03
java GC 관련  (0) 2011.06.16
[펌] DWR 설명과 사용법  (0) 2011.01.18
Posted by 달콤한녀석

댓글을 달아 주세요

  1. Un jeune homme de 24 ans doit être présenté au parquet lundi après la découverte, http://www.moncleroutletespain.com/ http://www.moncleroutletespain.com/, à Montpellier, du cadavre d'une jeune fille de 17 ans, tuée au cours de la nuit de la Saint-Sylvestre, http://www.moncleroutletespain.com/ moncler chaquetas. Selon le quotidien Midi Libre, http://www.moncleroutletespain.com/ moncler outlet, la victime aurait rencontré le jeune homme au cours du réveillon et aurait flirté avec lui, http://www.moncleroutletespain.com/ moncler. Le lendemain, sa mère, ne la voyant pas revenir, http://www.moncleroutletespain.com/ moncler online, a prévenu la police qui a interpellé le jeune homme en question. Lors de sa garde à vue celui-ci aurait reconnu avoir violé et tué la jeune fille avant d'indiquer où se trouver le corps aux enquêteurs, http://www.moncleroutletespain.com/ moncler españa, selon MidiLibre.Related articles:


    http://toothfairy.tistory.com/117 http://toothfairy.tistory.com/117

    http://lifeisgood.tistory.com/485 http://lifeisgood.tistory.com/485

    2013.01.05 16:32 [ ADDR : EDIT/ DEL : REPLY ]
  2. 처음엔 알 수 없던 너만의 향기가 느껴져, http://ypc.uggpaschermz.com ugg

    2013.04.11 06:59 [ ADDR : EDIT/ DEL : REPLY ]