SUN JVM 튜닝옵션 2013. 11. 01
목차 1. 개요... 3 2. JVM 특징소개... 3 3. JVM 주요옵션소개... 4 4. 분석기술... 9 2
1. 개요 SUN JVM 의특징을살펴보고, Trouble Shooting 방법과, 실제 Site 튜닝사례를살펴보도록한다. 2. JVM 특징소개 JVM 메모리영역. GC 알고리즘 Minor GC New 영역은 Eden 과 Survivor 두영역으로나뉘어지고, Survivor 는 Survivor1 과 Survivor2 로다시나뉘어진다. Eden 영역은객체가생성되자마자저장이되는곳이고, Minor GC 가발생하면 Eden 과 Survivor1 에사용한지오래되지않은객체를 Suvivor2 로복사한다. 그리고 Survivor1 과 Eden 영역을 Clear 한다. 다음번 Minor GC 가발생하면같은원리로 Eden 과 Survivor1 영역에서사용하던객체를 Survivor2 에복사한다. 계속이런방법을반복적으로수행하면서 Minor GC 를수행한다. 이렇게 Minor GC 를수행하다가, Survivor2 영역에서오래된객체는지정된비율에다다르면 Old 영역으로 옮겨지게된다. 객체생성시간이오래되면 Eden 영역이나 Survivor 영역에서 Old 영역으로이동을하게된다. Full GC Old 영역 GC 를 Full GC 라고부르며, Mark & Compact 알고리즘을이용한다. 이알고리즘은전체객체들의 reference tree 를찾아가면서연결되지않는객체를 Mark 한다. 이때사용되지않는객체를모두 Mark 가되고, 그다음으로객체를 Compact 기법으로사용하지않도록변경해버린다. 3
Full GC 는속도가느리기때문에, Full GC 가일어나는도중에는 thread 들의순간적으로 AP 가멈춰버리기 때문에, 성능과안정성에큰영향을준다. 다음장에서는 Full GC 시간을줄이기위한방법을알아보도록한다. 3. JVM 주요옵션소개 일반주요옵션 -Xnoclassgc Class Garbage Collection을수행하지않는다. -Xloggc:<file> GC Log를기록할파일명을지정한다. 파일명을지정하지않으면 Standard Out이나 Standard Error 콘솔에출력된다. 주로 -XX:+PrintGCTimeStamps, -XX:+PrintGCDetails 옵션과같이사용된다. -Xint Intepreter 모드로만 ByteCode를실행한다. Interpreter 모드로실행될경우에는 JIT Compile 기능이동작하지않는다. 이옵션을활성화하면실행속도이다소저하될수있다. 따라서 HotSpot Compiler의버그로문제가생길때만사용이권장된다. -Xmixed Mixed 모드로 ByteCode 를실행한다. HotSpot JVM 의 Default 동작방식이며, -Xint 옵션과상호배타적인옵션 이다 -Xms<size> Java Heap 의최초크기 (Start Size) 를지정한다. -Xmx<size> Java Heap 의최대크기 (Maximum Size) 를지정한다. -Xmn Young Generation 이거주하는 New Space 의크기를지정한다. 대개의경우이옵션보다는 -XX:NewRatio 옵션 이나 -XX:NewSize 옵션을많이사용한다 -Xss<size> 개별 Thread의 Stack Size를지정한다. 예를들어 Thread Stack Size가 1M이고, Thread가최대 100개활성화된다면, 최대 100M의메모리를사용하게된다. 대부분의경우기본값 (Default) 을그대로사용하는것이바람직하다. 많은수의 Thread를사용하는 Application의경우 Thread Stack에의한메모리요구량이높아지며이로인해 Out Of Memory Error가발생할수있다. 이런경우에는 -Xss 옵션을이용해 Thread Stack Size를줄여주어 4
야한다.(1.4 이하에서는 Thread 의 Native Stack Size 를의미 ) -Xoss<size> 개별 Thread 의 java stack Size 를지정한다. JDK5.0 부터는 Xss 로통합이되었으므로의미가없다. -XX:SurvivorRatio=8 Survivor Space와 Eden Space의비율을지정한다. 만일이값이 6이면, To Survivor Ratio:From Survivor Ratio:Eden Space = 1:1:6이된다. 즉, 하나의 Survivor Space의크기가 Young Generation의 1/8이된다. Survivor Space의크기가크면 Tenured Generation으로옮겨가기전의중간버퍼영역이커지는셈이다. 따라서 Full GC의빈도를줄이는역할을할수있다. 반면 Eden Space의크기가줄어들므로 Minor GC가자주발생하게된다. -XX:MaxHeapFreeRatio=70 Heap Shrinkage 를수행하는임계치를지정한다. 예를들어이값이 70 이면 Heap 의 Free 공간이 70% 이상이 되면 Heap 크기가축소된다. MinHeapFreeRatio 옵션과함께 Heap 의크기조정을담당한다. -XX:MinHeapFreeRatio=40 Heap Expansion 을수행하는임계치를지정한다. 예를들어이값이 40 이면 Heap 의 Free 공간이 40% 미만이 되면 Heap 크기가확대된다. MaxHeapFreeRatio 옵션과함께 Heap 의크기조정을담당한다. -XX:NewSize=2.125m Young Generation 의시작크기를지정한다. Young Generation 의크기는 NewSize 옵션 ( 시작크기 ) 과 MaxNewSize 옵션 ( 최대크기 ) 에의해결정된다. -XX:MaxNewSize=size Young Generation 의최대크기를지정한다. Young Generation 의시작크기는 NewSize 옵션에의해지정된다. -XX:PermSize Permanent Generation의최초크기를지정한다. Permanent Generation의최대크기는 MaxPermSize 옵션에의해지정된다. 많은수의 Class를로딩하는 Application은큰크기의 Permanent Generation을필요로하며, Permanent Generation의크기가작아서 Class를로딩하는못하면 Out Of Memory Error가발생한다. -XX:MaxPermSize=64m Permanent Generation의최대크기를지정한다. Permanent Generation의시작크기는 PermSize 옵션에의해지정된다. 많은수의 Class를 Loading하는 Application은 PermSize와 MaxPermSize 옵션을이용해 Permanent Generation의크기를크게해주는것이좋다. Permanent Generation의크기가작을경우에는 Out Of Memory Error가발생할수있다. 5
-XX:NewRatio=2 Young Generation과 Old Generation의비율을결정한다. 예를들어이값이 2이면 Young:Old = 1:2 가되고, Young Generation의크기는전체 Java Heap의 1/3이된다 [sparc -server: 2, sparc -client: 4 (1.3) 8 (1.3.1+), intel: 12] -XX:+DisableExplicitGC System.gc 호출에의한 Explicit GC 를비활성화한다. RMI 에의한 Explicit GC 나 Application 에서의 Explicit GC 를 원천적으로방지하고자할경우에사용된다. GC 종류에따른옵션 -XX:+UseParallelGC Throughput Garbage Collector는 New Generation에의한 Minor GC 작업을여러개의 Thread(CPU의개수만큼 ) 를이용해 Parallel하게진행한다 Server 급머신에서는이 Collector가기본설정이라는것은의미하는바가크다. 특히 CPU 자원이풍부한환경에서는큰효과를얻을수있다. -XX:ParallelGCThreads 옵션을이용하면 Parallel Collector Threads의개수를조절할수있다. -XX:+UseConcMarkSweepGC Throughput Garbage Collector와는달리 Response Time를최적화하게끔동작한다. 정확하게말하면 Response Time을최소화하기위해 Full GC 과정을되도록이면 Thread 블로킹없이진행한다. Thread의정지시간 (Pause Time) 이최소화되기때문에 Low Pause Garbage Collector라는이름이붙었다. -XX:+UseParNewGC CMS 를사용할경우 Minor GC 를 Parallel 하게할지의여부를지정한다. CPU 가복수개일경우는기본적으로 이모드를사용한다. -XX:+CMSParallelRemarkEnabled -XX:+UseParNewGC 와함께사용할경우 GC 대상을표시하기위하여잠시멈추는현상을줄인다 -XX:CMSInitiatingOccupancyFraction 만일이값이 60이면 Old 영역의 60% 가사용되는시점에 Concurrent GC 작업이시작된다. 만일이값이너무크면제때 GC가이루어지지못해 Mark and Sweep GC가작동할확률이높아진다. 반면이값이너무작으면 Concurrent GC 작업이너무일찍시작해서 Application Thread의 CPU 점유를방해한다. 따라서처리량 (Throughput) 이낮아질수있다. 6
-XX:MaxTenuringThreshold default값은 31로, eden 영역의객체가 survivor영역으로옮겨져서최종적으로 old영역으로옮겨지기까지최대로복사를 31번까지할수있다는것을의미한다. 0으로하게되면바로 old영역으로옮겨가게되어복사되는시간을줄이게된다. 디버그옵션 -XX:-PrintGCDetails GC 발생시 Heap 영역에대한비교적상세한정보를추가적으로기록한다. 추가적인정보는 {GC 전후의 Young/Old Generation의크기, GC 전후의 Permanent Generation의크기, GC 작업에소요된시간 } 등이다. Minor GC가발생한경우 PrintGCDetails 옵션의적용예는아래와같다. [GC [DefNew: 64575K->959K(64576K), 0.0457646 secs] 196016K->133633K(261184K), 0.0459067 secs]] 위의로그가의미하는바는다음과같다. GC 전의 Young Generation Usage = 64M, Young Generation Size = 64M GC 전의 Total Heap Usage = 196M, Total Heap Size = 260M GC 후의 Young Generation Usage = 9.5M GC 후의 Total Heap Usage = 133M Minor GC 소요시간 = 0.0457646 초 Major GC가발생한경우 PrintGCDetails 옵션의적용예는아래와같다. 111.042: [GC 111.042: [DefNew: 8128K->8128K(8128K), 0.0000505 secs] 111.042: [Tenured: 18154K->2311K(24576K), 0.1290354 secs] 26282K->2311K(32704K), 0.1293306 secs] 위의로그는 Minor GC 정보외에다음과같은 Major GC 정보를제공한다. GC 전의 Tenured Generation Usage = 18M, Tenured Generation Size = 24M GC 후의 Tenured Generation Usage = 2.3M Major GC 소요시간 = 0.12초 ( 참고 ) PrintGCDetails + PrintGCTimeStamps 옵션의조합이가장보편적으로사용된다. -XX:-PrintGCTimeStamps GC 가발생한시간을 JVM 의최초구동시간기준으로기록한다. -XX:+PrintHeapAtGC GC 발생전후의 Heap 에대한정보를상세하게기록한다 -XX:HeapDumpPath=./java_pid<pid>.hprof HeapDump 에대한파일명과경로를지정한다. (1.4.2_12, 5.0 update 7 이상에서사용가능하다.) 7
-XX:-HeapDumpOnOutOfMemoryError OutOfMemory 가났을경우 HeapDump 를생성한다. (1.4.2_12, 5.0 update 7 이상에서사용가능하다.) -XX:OnOutOfMemoryError="<cmd args>" OutOfMemory 가발생했을경우특정 command 를수행한다. (1.4.2_12 이상과 jdk6 에서사용가능하다.) 기타옵션 -Xrs OS Signal 사용을최소화한다. 가령이옵션을켜면 kill -3 [pid] 명령을수행해도 Thread dump 가발생하지않 는다. -XX:MaxGCPauseMillis GC 에의한 Pause Time 을 <value>ms 이하가되게끔 Heap 크기와기타옵션들을자동으로조정하는기능을 한다. -XX:+MaxFDLimit JVM 의 File Descriptoer 값을 OS 의 max 값으로설정한다. -XX:+ScavengeBeforeFullGC Full GC 하기이전에 Minor GC 를수행한다. -XX:+UseAltSigs Solaris 운영체제에서 VM은디폴트로 SIGUSR1을사용한다. 이것은 SIGUSR1을시그널체인 (signal-chain) 하는애플리케이션과충돌하는경우이옵션은 default로 SIGUSR2 사용하도록할수있다. -XX:+UseBoundThreads Solaris 에서제공하는 kernel 단의 thread 를사용하는옵션으로, CPU resource 가부족하여 thread 들이더이상 진행되지못하는 thread 부족현상을감소시킬수있다. -XX:-UseParallelOldGC Old 영역에대해 ParallelGC 를수행한다. (JDK6 에서포함 ) 8
-XX:-UseSerialGC JDK 1.4에서는이 Collector가기본설정이다. JDK 5.0에서는만일 JVM이실행되는환경이 Server 급이라면 Throughput Garbage Collector가기본설정이된다. -XX:ThreadStackSiz Solaris Thread Stack Size를설정한다.(kbyte) -XX: TargetSurvivorRatio=50 객체가 survivor영역에서 Old 영역으로이동하기전까지 survivor영역이사용되어야하는퍼센트수치 4. 분석기술 GC 알고리즘의이해 SUN Hot-Spot JDK 에서는, 아래와같이주요 4 가지 Garbage Collection 옵션을제공한다. 이들은아래와같은설정으로설정이가능하다. 1. Default garbage collector 구분설명옵션 -XX:+UseSerialGC 설명 JDK1.4에서는 default이다. JDK 5에서는서버급 (2CPU,2G메모리) 일경우에는 Parallel GC가선택된다. 전통적인 GC방법으로 Minor GC에 Scavenge를, Full GC에 Mark & compact 알고리즘을사용하는방법이다 2. Parallel garbage collector 구분 옵션 설명 설명 -XX:+UseParallelGC JDK 1.4 부터지원되는 Parallel GC 는 Minor GC 를동시에여러개의 Thread 를이용해서 GC 를수행하는방법으로하나의 Thread 를이용하는것보다훨씬빨리 GC 를수행할수있다. 이때반드시고려되어야하는것이 CPU 개수이다. 시스템적으로계산하기위해 CPU 를사용하기때문에최소 4CPU 이상에서만최적의성능을보인다. Parallel GC 는두가지로나뉘는데,Low-pause 방식과 Throughput 방식이다. Solaris 에서는 Low-pause Parallel GC 는 -XX:+UseParNewGC 옵션을사용한다. Old 영역을 GC 할때 Concurrent GC 방법과함께사용할수있다. 이방법은 GC 가일어날때빨리 GC 하는것이아니라 GC 가발생할때 Application 이멈추는현상을줄이는데초점이맞춰져있다. Throughput 방식의 Parallel GC 는 -XX:+UseParallelGC (Solaris 기준 ) 옵션을이용하며 Old 영역을 GC 할때는 Default GC (Mark and compact) 방법만을사용하도록되어있다.Minor GC 가발생했을때, 되도록이면빨리수행하도록하는데초점이있다. 또한동시에몇개의 Thread 를이용하여 Minor 영역을 Parallel GC 할지를결정할수있는데, - XX:ParallelGCThreads= 옵션을사용하여수를지정할수있다. 9
3. Concurrent garbage collector 구분설명옵션 -XX:+UseConcMarkSweepGC 설명 Full GC 즉 Old 영역을 GC 하는경우에는그시간이길고 Application 이순간적으로멈춰버리기때문에, 시스템운용에문제가된다. 그래서 JDK1.4 부터제공하는 Concurrent GC 는기존의이런 Full GC 의단점을보완하기위해서 Full GC 에의해서 Application 이멈추어지는현상을최소화하기위한 GC 방법이다. Full GC 에소요되는작업을 Application 을멈추고진행하는것이아니라, 일부는 Application 이돌아가는단계에서수행하고, 최소한의작업만을 Application 이멈췄을때수행하는방법으로 Application 이멈추는시간을최소화한다. Application 이수행중일때 Full GC 를위한작업을수행한다. (Sweep,mark) Application 을멈추고수행하는작업은일부분 (initial-mark, remark 작업 ) 만을수행하기때문에, 기존 Default GC 의 Mark & Sweep Collector 에비해서 Application 이멈추는시간이현저하게줄어든다. Solaris JVM 에서는 -XX:+UseConcMarkSweepGC Parameter 를이용해세팅한다. GC 로그출력과이해 -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+PrintGCApplicationStoppedTime 옵션을적용하여 Collector 별로그를분석해보도록한다. 일반적으로 GC 로그는다음과같다. "GC 종류종류 : 이전사용메모리 -> GC 이후사용메모리 ( 전체사이즈 ), 시간 " "DefNew: 18175K->1983K(18176K), 0.0357371 secs" 는다음과같은사실을의미한다. New Generation 에대해 Serial GC 를수행했으며 GC 전에는 18M(18175K) 를쓰고있었고, GC 이후 1.9M(1983K) 를쓰고있다. New Generation 의전체크기는 18M(18176K) 이다. GC 를수행하는데는 0.035 초정도걸렸다. 1. Default GC Log 0.109: [GC 0.110: [DefNew: 104K->64K(2112K), 0.0042610 secs]0.114: [Tenured: 18K->82K(1408K), 0.0088914 secs] 104K->82K(3520K), 0.0133819 secs] Total time for which application threads were stopped: 0.0147430 seconds JDK1.4 에서는 default 로사용하고있는 GC 로위와같은형태로나오게된다. 10
2. Parallel GC Log 3.303: [GC [PSYoungGen: 15168K->3712K(15744K)] 251928K->244204K(257728K), 0.0386683 secs] 3.341: [Full GC [PSYoungGen: 3712K->0K(15744K)] [PSOldGen: 240492K->95306K(241984K)] 244204K- >95306K(257728K) [PSPermGen: 1836K->1836K(16384K)], 0.4015217 secs] Serial Collector 에서 DefNew 로표기되었던것이 PSYoungGen 으로표기된다. Throughput Collector 의개념을이해했다면그차이를정확하게알수있을것이다. 3. Concurrent GC Log 9.936: [GC [1 CMS-initial-mark: 173808K(253952K)] 174918K(262080K), 0.0011353 secs] Total time for which application threads were stopped: 0.0029149 seconds 9.937: [CMS-concurrent-mark-start] 9.956: [GC 9.956: [ParNew: 8064K->0K(8128K), 0.0216583 secs] 181872K->176390K(262080K), 0.0217720 secs]... 10.036: [GC 10.036: [ParNew: 8064K->0K(8128K), 0.0200405 secs] 187044K->181580K(262080K), 0.0201724 secs] 10.060: [CMS-concurrent-mark: 0.057/0.123 secs] 10.060: [CMS-concurrent-preclean-start] 10.061: [CMS-concurrent-preclean: 0.000/0.000 secs]... 10.189: [GC[YG occupancy: 8064 K (8128 K)]10.190: [Rescan (parallel), 0.0111151 secs] 10.201: [weak refs processing, 0.0000221 secs] [1 CMS-remark: 191976K(253952K)] 200040K(262080K), 0.0113344 secs]... 10.663: [CMS-concurrent-sweep: 0.256/0.461 secs] 10.663: [CMS-concurrent-reset-start] 10.670: [CMS-concurrent-reset: 0.007/0.007 secs] Serial Collector 에서 DefNew 로표기되었던것이 ParNew 로표기되는것에주의한다. -XX:+UseParNewGC 옵션이작동한결과이다. CMS 로시작하는부분은 initial mark->concurrent mark -> remark -> concurrent sweep 으로이어지는 Full GC 의활동상황이기록된것이다. jstat 을이용한실시간메모리영역모니터링 JDK5 에서추가된 jstat 를사용하여다른 jvm 의실시간메모리상태를보는방법이있는데따로 GC 옵션을 걸지않았을경우에유용하게사용될수있다. 우선 jps 명령어로 pid 를알아낸다. 11
jps grep EngineContainerBootstrapper 21778 EngineContainerBootstrapper jstat -gc -h3 21778 1s S0C S1C S0U S1U EC EU OC OU PC PU YGC YGCT FGC FGCT GCT 384.0 448.0 0.0 0.0 1047680.0 66763.1 1024000.0 18322.2 45056.0 42329.6 399 105.318 125 91.938 197.256 384.0 448.0 0.0 0.0 1047680.0 66763.1 1024000.0 18322.2 45056.0 42329.6 399 105.318 125 91.938 197.256 384.0 448.0 0.0 0.0 1047680.0 66763.1 1024000.0 18322.2 45056.0 42329.6 399 105.318 125 91.938 197.256 S0C S1C S0U S1U EC EU OC OU PC PU YGC YGCT FGC FGCT GCT 384.0 448.0 0.0 0.0 1047680.0 66763.1 1024000.0 18322.2 45056.0 42329.6 399 105.318 125 91.938 197.256 384.0 448.0 0.0 0.0 1047680.0 66763.1 1024000.0 18322.2 45056.0 42329.6 399 105.318 125 91.938 197.256 384.0 448.0 0.0 0.0 1047680.0 66763.1 1024000.0 18322.2 45056.0 42329.6 399 105.318 125 91.938 197.256 -gc 옵션이외에도상세상태를볼수있는옵션을제공한다. -h3 는 header 를 3 번마다출력하는옵션이고 1s 는 1 초마다출력을하는옵션이다. 헤더별의미는다음과같다. S0, S1: survivor 의두영역 E: Eden 영역 O: Old 영역 P: Perm 영역 YGC: 마지막 Young GC Count( 횟수 ) YGCT: 마지막 Young GC Time( 시간 ) FGC: 마지막 Full GC Count( 횟수 ) FGCT: 마지막 Full GC Time( 시간 ) GCT: (YoungGC + FullGC ) 마지막 GC Time jconsole 을이용한실시간 GUI 모니터링이번에도 JDK5 에서제공하는 jconsole 을이용하여메모리상태를실시간으로보는방법에대해알아본다. jconsole 은 jmxremote 로통신을하므로 JEUSMain.xml 의 <command-option> 에 - Dcom.sun.management.jmxremote 가추가되어야한다. 12
windows 에서는직접사용이가능하나, Unix 환경에서는 XManager 를사용하여야구동이가능하다. 위그림과같이 XManager 의 XStart 를구동한다. 구동을한후다음과같이 display 세팅을해준다. export DISPLAY= 로컬 PC 아이피 :0.0 Memory tab 을누르면아래와같이 Eden, Survivor, Old, Perm 영역들의세부내역을 GUI 로볼수있게된다. 또한 Thread 탭에서는덤프를생성하지않고서도, 각 Thread 의실시간 Trace 를확인할수있다. 단속도가 느리다는것이단점이다. 13
Heap Dump 분석 1. Heap Dump 생성 HeapDump 를생성하는방법은다음의 4 가지가있다. 1. JDK1.4.2_12,JDK5.0 update7 에서부터가능한 -XX:+HeapDumpOnOutOfMemoryError 옵션을적용하게되면 OutOfMemory 가발생했을경우 HeapDump 를생성하게된다. default 로는 java_pid<pid>.hprof 이고 - XX:HeapDumpPath 로경로를지정할수있다. 2. JDK1.4.2_12,JDK5.0 update14 에서부터가능한 -XX:+HeapDumpOnCtrlBreak 을적용하면 Ctrl+ Break 나 SIGQUIT(kill -3) signal 을받았을경우 HeapDump 를생성한다. 3. JDK5.0 에서추가된옵션으로 -agentlib:hprof=file=dump.hprof,format=b 를 JVM 실행시에추가한다. 4. JDK1.4.2_09 에서추가된 jmap 을이용하여다음과같이덤프를생성한다. jmap -heap:format=b PID_OF_PROCESS (jdk5) jmap -dump:format=b,file=snapshot2.jmap PID_OF_PROCESS ( jdk6) 2. hat 으로 Heap Dump 분석이렇게생성된파일을분석하기위해서는 jdk6 에포함되어있는 jhat 를사용하여야하거나, jdk5 는별도로 download(http://hat.dev.java.net) 를받아야한다. 우선위의옵션들중하나를선택하여 dump 를생성한다. 로컬이나서버에서 hat 을다운받아설치하거나 jdk6 에있는 jhat 을이용하여실행한다. jhat dump.hprof 14
Started HTTP server on port 7000 Server is ready. 위와같이하면분석은모두끝난상태이고, 결과는위의 7000 번포트를웹브라우저로접근하여볼수있다. 여기에서 heap histogram 을누르면 JVM 의메모리에로드된객체들의통계를볼수있다. 3. IBM ha 로 Heap Dump 분석 IBM 의 HA 로도분석이가능한데, 아래의주소에서다운로드받을수있다. http://www.alphaworks.ibm.com/tech/heapanalyzer/download/ 15
Copyright 2013 TmaxSoft Co., Ltd. All Rights Reserved. TmaxSoft Co., Ltd. Trademarks Tmax, WebtoB, WebT, JEUS, ProFrame, SysMaster and OpenFrame are registered trademarks of TmaxSoft Co., Ltd. Other products, titles or services may be registered trademarks of their respective companies. Contact Information TmaxSoft can be contacted at the following addresses to arrange for a consulting team to visit your company and discuss your options for legacy modernization. Korea - TmaxSoft Co., Ltd. Corporate Headquarters 272-6 Seohyeon-dong, Bundang-gu, Seongnam-si, South Korea, 463-824 Tel : (+82) 31-8018-1708 Fax : (+82) 31-8018- 1710 Website : http://tmaxsoft.com U.S.A. - TmaxSoft Inc. 560 Sylvan Avenue Englewood Cliffs, NJ 07632, USA Tel : (+1) 201-567-8266 Fax : (+1) 201-567- 7339 Website : http://us.tmaxsoft.com Japan TmaxSoft Japan Co., Ltd. 5F Sanko Bldg, 3-12-16 Mita, Minato-Ku, Tokyo, 108-0073 Japan Tel : (+81) 3-5765-2550 Fax: (+81) 3-5765- 2567 Website : http://jp.tmaxsoft.com China TmaxSoft China Co., Ltd. Room 1101, Building B, Recreo International Center, East Road Wang Jing, Chaoyang District, Beijing, 100102, P.R.C Tel : (+86) 10-5783-9188 Fax: (+86) 10-5783- 9188(#800) Website : http://cn.tmaxsoft.com China(JV) Upright(Beijing) Software Technology Co., Ltd Room 1102, Building B, Recreo International Center, East Road Wang Jing, Chaoyang District, Beijing, 100102, P.R.C Tel : (+86) 10-5783-9188 Fax: (+86) 10-5783- 9188(#800) Website : www.uprightsoft.com TD-JSTN-C1101016 16