1. 미들웨어이야기/01. JVM

IBM JVM (1.5 기준)

OSSW(Open Source System SoftWare 2009. 6. 16. 10:57

Sun Hotspot JVM 반드시 Command Line에서 JVM Option 지정해주어야 하는 반면, IBM JVM에서는 다음과 같은 가지 방법으로 Option 지정할 있다.

*   Command Line: java -Xgcpolicy:optthruput 같은 형태로 지정

*   Options File: –Xoptionsfile 옵션을 이용해서 Option 모아둔 Text File 지정. Optionsfile 다음과 같은 형태이다.

#My options file

-X<option1>

-X<option2>=\<value1>,\

      <value2>

-D<sysprop1>=<value1>

*   IBM_JAVA_OPTIONS 환경변수: IBM_JAVA_OPTIONS 환경변수에 값을 지정(: IBM_JAVA_OPTIONS=-X<option1> -X<option2>=<value1>)

 

Standard Options

Option

Description

-memorycheck:<optiton>

JVM 내부에서 발생하는 Memory Leak 추적하기 위한 용도로 사용된다. JVM 기술지원 엔지니어들이 사용하는 용도로 보면 정확한다. JVM 자체는 C/C++ 구현되었다. 따라서 JVM 내부에서 발생하는 Memory Leak Java에서 발생하는 것과는 달리 진정한 의미에서는 Memory Leak으로 이해할 있다. 다음과 같은 옵션들이 제공된다(IBM JVM Diagnositics Guide에서 발췌)

*   all - The default if just -memorycheck is used. Enables checking of all allocated and freed blocks on every free and allocate call. This check of the heap is the most thorough and should cause the JVM to exit on nearly all memory-related problems very soon after they are caused. This option has the greatest impact on performance.

*   quick - Enables block padding only. Used to detect basic heap corruption. Pads every allocated block with sentinel bytes, which are verified on every allocate and free. Block padding is faster than the default of checking every block, but is not as effective.

*   nofree - Keeps a list of already used blocks instead of freeing memory. This list is checked, along with currently allocated blocks, for memory corruption on every allocation and deallocation. Use this option to detect a dangling pointer (a pointer that is "dereferenced" after its target memory is freed). This option cannot be reliably used with long-running applications (such as WAS), because "freed" memory is never reused or released by the JVM.

*   failat=<number of allocations> - Causes memory allocation to fail (return NULL) after <number of allocations>. Setting <number of allocations> to 13 will cause the 14th allocation to return NULL. Deallocations are not counted. Use this option to ensure that JVM code reliably handles allocation failures. This option is useful for checking allocation site behavior rather than setting a specific allocation limit.

*   skipto=<number of allocations> - Causes the program to check only on allocations that occur after <number of allocations>. Deallocations are not counted. Used to speed up JVM startup when early allocations are not causing the memory problem. As a rough estimate, the JVM performs 250+ allocations during startup.

*   callsite=<number of allocations> - Prints callsite information every <number of allocations>. Deallocations are not counted. Callsite information is presented in a table with separate information for each callsite. Statistics include the number and size of allocation and free requests since the last report, and the number of the allocation request responsible for the largest allocation from each site. Callsites are presented as sourcefile:linenumber for C code and assembly function name for assembler code. Callsites that do not provide callsite information are accumulated into an "unknown" entry.

*   zero - Newly allocated blocks are set 0 instead of being filled with the 0xE7E7xxxxxxxxE7E7 pattern. Setting to 0 helps you to determine whether a callsite is expecting zeroed memory (in which case the allocation request should be followed by memset(pointer, 0, size)).

-showversion

Java 버전과 기본적인 사용법에 대한 정보를 제공한다.

-verbose:<option>

Option 따라 상세 정보를 출력한다. 다음과 같은 옵션이 제공된다.

*   class - Class Loading 정보를 Standard Err 출력한다. 출력 예는 아래와 같다.

class load: java/io/FilePermission

class load: java/io/FilePermissionCollection

class load: java/security/AllPermission

...

class load: test

class load: test from: file:/C:/Documents/Java_Test/GC%20dump/

*  dynload - Class Loading 대한 매우 상세한 정보를 제공한다. 클래스명, 클래스 크기, 로딩 시간등의 정보를 포함한다. 출력 예는 아래와 같다.

<  Class size 6594; ROM size 7056; debug size 0>

<  Read time 128 usec; Load time 126 usec; Translate time 222 usec>

<Loaded java/security/BasicPermissionCollection from c:\IBM\WebSphere\AppServer\java\jre\lib\core.jar>

<  Class size 4143; ROM size 3264; debug size 0>

<  Read time 103 usec; Load time 81 usec; Translate time 117 usec>

<Loaded java/security/Principal from c:\IBM\WebSphere\AppServer\java\jre\lib\core.jar>

<  Class size 239; ROM size 248; debug size 0>

<  Read time 44 usec; Load time 23 usec; Translate time 20 usec>

<Loaded test>

<  Class size 370; ROM size 448; debug size 0>

<  Read time 0 usec; Load time 28 usec; Translate time 39 usec>

*  gc - GC 작업에 대한 정보를 제공한다. 자세한 내용은 GC Dump 참조한다.

*  jni - JNI 호출에 대한 정보를 제공한다. 출력 예는 아래와 같다.

<JNI ReleaseStringChars: buffer=41EC45B8>

<JNI GetStaticMethodID: gc_dump.main ([Ljava/lang/String;)V>

<JNI GetMethodID: java/lang/reflect/Method.getModifiers ()I>

<JNI GetMethodID: java/lang/String.<init> ([B)V>

<JNI FindClass: java/lang/Object>

<JNI GetMethodID: java/lang/Object.finalize ()V>

<JNI FindClass: java/lang/ref/Reference>

<JNI GetMethodID: java/lang/ref/Reference.enqueueImpl ()Z>

*   sizes - Memory 사용과 관련된 설정값을 출력한다. 출력 예는 아래와 같다.

 -Xmca32K              RAM class segment increment

 -Xmco128K            ROM class segment increment

 -Xmns0K                initial new space size

 -Xmnx0K                maximum new space size

 -Xms4M                 initial memory size

 -Xmos4M               initial old space size

 -Xmox1047608K     maximum old space size

 -Xmx1047608K       memory maximum

 -Xmr16K               remembered set size

 -Xmso32K             OS thread stack size

 -Xiss2K                java thread stack initial size

 -Xssi16K              java thread stack increment

 -Xss256K             java thread stack maximum size

 -Xscmx16M          shared class cache size

*   stacks - Thread 별로 Java/C Stack 사용 크기를 출력한다. 출력 예는 아래와 같다.

JVMVERB000I Verbose stack: "Thread-1" used 188/3756 bytes on Java/C stacks

JVMVERB000I Verbose stack: "Thread-2" used 516/3756 bytes on Java/C stacks

JVMVERB000I Verbose stack: "main" used 1368/0 bytes on Java/C stacks

JVMVERB000I Verbose stack: "Finalizer thread" used 456/2308 bytes on Java/C stacks

JVMVERB000I Verbose stack: "Gc Slave Thread" used 232/3060 bytes on Java/C stacks

Non-Standard Options

Option

Default

Description

-Xalwaysclassgc

-Xclassgc 옵션에 의해 결정됨

Global Collection 발생할 Class GC 수행할 지의 여부를 지정한다. classgc 옵션과 동일한 값이며, Default True이다.

-Xbootclasspath

Sun JVM bootclasspath 옵션과 동일

-Xcheck:jni

False

Sun JVM check:jni 옵션과 동일

-Xclassgc

True

Classloader 변했을 때만 Class GC 수행할 지의 여부를 결정한다.

-Xcodecache<size>

OS/Hardware Architecture 따라 결정됨

-Xcomp

-Xjit:count=0 옵션을 사용한 것과 동일. z/OS에서만 사용되며, deprecated 옵션이다.

-Xcompactexplicitgc

False

System.gc() 호출에 의한 Explicit GC 발생했을 경우 항상 Compaction 수행할 지의 여부를 결정한다. Sun Hotspot JVM 경우에는 System.gc() 호출이 발생할 경우 반드시 Full GC 수행한다. 반면 IBM JVM 경우에는 이전 GC 작업에서 Compaction 발생하지 않은 경우에만 Compaction 수행한다.

-Xcompactgc

False

System GC Global GC 발생할 때마다 Compaction 수행한다.

-Xconcurrentbackground

1

Response Time Collector에서 Concurrent Mark 수행할 Background Thread 개수를 지정한다. Concurrent Background Thread Application Thread 성능을 다소 저하시킬 있으므로 하나만 구동하는 것이 바람직하다. , Concurrent Mark 작업이 진행되지 않아 문제가 생기는 경우에는 값을 키우는 것이 해결책이 있다.

-Xconcurrentlevel<value>

-Xconmeter<option>

-Xdisableexcessivegc

False

GC 작업에 지나치게 많은(Excessive) 시간이 소요된 경우에 Out Of Memory Error 유발하지 않도록 지정한다.

-Xdisableexplicitgc

False

System.gc() 호출에 의한 GC 작업을 비활성화한다. 옵션을 사용하면 System.gc() 호출하더라도 GC 작업이 발생하지 않는다. RMI 의한 불필요한 GC 작업이나 사용자의 실수에 의한 강제적인 GC 작업을 방지하고자 하는 목적으로 사용된다.

-Xdisablejavadump

False

Java Dump 생성을 비활성화시킨다. IBM JVM 치명적인 Error Signal 받으면 Java Dump 생성함으로써 사후 문제를 디버깅할 있도록 한다. 특정 문제로 인해 지나치게 많은 Dump 생성될 옵션을 비활성시키는 경우가 있다.

-Xdisablestringconstantgc

False

Interned String 대한 GC 작업을 비활성화한다.

-Xenableexcessivegc

True

GC 작업에 지나치게 많은(Excessive) 시간이 소요된 경우에 Out Of Memory Error 유발하도록 지정한다. disableexcessivegc 반대의 역할을 한다.

-Xenablestringconstantgc

True

Interned String 대한 GC 작업을 활성화한다. disablestringconstantgc 옵션과 반대의 역할을 한다.

-Xgcpolicy<option>

optthruput

Garbage Collector 종류를 결정한다.

*  optthruput: Throughput Collector 사용한다. 처리량(Throughput) 최적화할 목적으로 사용되며, Default Collector이다.

*  optavgpause: Response Time Collector 사용한다. 응답시간(Response Time) 최적화할 목적으로 사용된다. GC 의한 Pause Time 최소하기 위해 Concurrent Mark/Sweep 작업을 수행한다. Throughput Collector 비해 처리량으로 다소(5~10%) 떨어진다.

*  gencon: Concurrent Generational Collector 사용한다. IBM JDK 1.5에서 추가되었다. Sun Hotspot JVM CMS Collector 거의 동일한 방식으로 동작하다.

*  subpool: Subpool Collector 사용한다.

-Xgcthreads<value>

CPU#

Throughput Collector Mark & Sweep 작업을 Parallel하게, 동시에 여러 Thread 사용해서 수행한다. 옵션을 통해 Parallel GC 수행할 Thread 수를 지정한다. 기본적으로 CPU 개수를 모두 활용한다. 만일 하나의 Machine에서 여러 JVM 구동하거나, 다른 종류의 Application JVM 공존하는 경우에는 값을 줄임으로써 Context Switching 의한 성능 저하를 피할 있다.

gcworkpackets

int

iss

-Xjit:<options>

True(JIT 컴파일을 사용함)

JIT 컴파일 옵션을 결정한다. <options> 지정되지 않으면 단순히 JIT 컴파일을 활성화한다. 옵션은 JIT 컴파일러의 버그로 인해 JVM 장애에 대해 Workaround 많이 활용된다.

JIT 컴파일러의 버그에 의한 JVM Crash 발생할 경우에는 다음과 같은 유형의 Error Stacktrace 기록된다.

...

TR_GlobalRegisterAllocator::perform()

TR_OptimizerImpl::performOptimization()

TR_OptimizerImpl::performOptimization()

TR_OptimizerImpl::optimize()

...

경우에는 다음과 같은 옵션을 이용해서 JIT 컴파일을 제어할 있다.

# Inlining 비활성화한다.

-Xjit:disableInlining

-Xjit:{java/lang/Math.max(II)I}(disableInlining)

 

# 특정 메소드를 Optimization에서 제외한다.

-Xjit:exclude={java/lang/Math.max(II)I} ...

아래 옵션들은 JIT 컴파일러에 문제가 발생한 경우 이를 쉽제 추적하고자 사용된다.

count=<n>

   <n> 수행에서 Method JIT 컴파일한다. JIT 문제를 추적할 때는 "0" 값을 사용함으로써 보다 빨리 컴파일이 이루어지도록 한다.   

optlevel=[noOpt | cold | warm | hot | veryHot | scorching]

   [비최적화 ~ 최고 최적화]까지 JIT 컴파일에 의한 최적화 레벨을 지적한다.

verbose

   JIT 컴파일 과정에서 사용된 정보와 컴파일 과정을 출력한다.

아래에 -Xjit:verbose 옵션의 출력 예가 있다. count 값은 1000, optlevel 값은 warm 기본값임을 있다.

JIT type: Testarossa (Full)

JIT options specified:

    verbose

options in effect:

    bcount=250

    catchSamplingSizeThreshold=1100

    classLoadPhaseInterval=500

    classLoadPhaseThreshold=155

    code=512 (KB)

    codepad=0 (KB)

    codetotal=0 (KB)

    count=1000

    ...

    stack=256

    target=ia32-win32

    verbose=1

 

+ (warm) java/lang/Double.doubleToRawLongBits(D)J @ 0x41630014-0x41630030

+ (warm) java/lang/System.getEncoding(I)Ljava/lang/String; @ 0x41630054-0x41630145

+ (warm) java/lang/String.hashCode()I @ 0x4163017C-0x4163024A

+ (warm) java/util/HashMap.put(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; @ 0x4163027C-0x416304AF

+ (warm) java/util/Locale.toLowerCase(Ljava/lang/String;)Ljava/lang/String; @ 0x416304DC-0x416307FF

...

+ (warm) java/io/FileOutputStream.writeBytes([BIILjava/io/FileDescriptor;)V @ 0x41636C34-0x41636D45|-