Runtime Data Areas 엑셈컨설팅본부 /APM 팀임대호 Runtime Data Area 구조 Runtime Data Area 는 JVM 이프로그램을수행하기위해할당받는메모리영역이라고할수있다. 실제 WAS 성능문제에직면했을때, 대부분의문제점은 Runtime Data Area 에서발생하는경우가많다. Memory Leak 이나 Garbage Collection 인경우가그예이다. 이러한성능문제가발생할시이문제가왜발생한것인지어디에서발생한것인지확인하는것은쉽지않다. 이러한경우 Runtime Data Area 의아키텍처를공부하는것이해당문제를분석하는데큰도움이될것이다. Runtime Data Area 는크게다섯가지영역으로나뉘게된다. 그것은 PC Register, Java Virtual Machine Stacks, Native Method Stacks, Method Area, Heap 이다. 각 Thread 별로생기는영역은 PC Register, Java Virtual Machine Stacks, Native Method Stacks 이고, 모든 Thread 가공유하는영역은 Method Area 와 Heap 이다. [ 그림 1] Runtime Data Area 450 2013 기술백서 White Paper
PC Register Java 의 PC Register 는 CPU 내의기억장치인레지스터와는다르게작동한다. Register-Base 가아닌 Stack-Base 로동작한다. PC Register 는각 Thread 별로하나씩존재하며현재수행중인 Java Virtual Machine Instruction 의주소를가지게된다. 만일 Native Method 를수행한다면 PC Register 는 Undefined 상태가된다. 이 PC Register 에저장되는 Instruction 의주소는 Native Pointer 일수도있고 Method Bytecode 일수도있다. Native Method 를수행할때에는 JVM 을거치지않고 API 를통해바로수행하게된다. 이는 Java 는 Platform 에종속받지않는다는것을보여준다. Java Virtual Machine Stacks Java virtual Machine Stacks 은 Thread 의수행정보를 Frame 을통해서저장하게된다. Java Virtual Machine Stacks 는 Thread 가시작될때생성되며, 각 Thread 별로생성이되기때문에다른 Thread 는접근할수없다. 대표적으로 Local variable 를가진다. [ 그림 2] Java Virtual Machine Stacks Part 2 APM 451
Java Virtual Machine Stacks 에서현재수행하고있는 Frame 을 Current Frame 이라고한다. Stack Frame 에는 Method 의 Parameter variable, Local variable 과연산결과를저장하게 된다. Stack Frame Stack Frame 은 Thread 가수행하고있는 Method 단위를기록하는곳이다. Method 의상태정보를저장하는 Stack Frame 은크게세가지영역으로나뉜다. 그것은 Local Variable Section, Operand Stack, Frame Data 이다. Stack Frame 의크기는컴파일때결정이난다. Local Variable Section Local Variable Section 은 Method 의 Parameter Value 와 Local Variable 을저장한다. Local Variable Section 은 0 부터시작하는 array 형인덱스를가지는데 parameter value 부터할당된다. Local Variable 은순서가정해져있지않다. 또한만약사용되지않으면할당되지않을수도있다. Parameter Value 와 Local Variable 가 Primitive Type 인경우 (ex int 형 ) 는고정된크기로할당된다. 하지만 String 이나 Array 같은객체는가변크기이므로 Reference 를갖는다. Java source class Test { public int testmethod (int a, char b, long c, float d, object e, double f, String g, byte h, short I, Boolean j) {return 0; } 452 2013 기술백서 White Paper
[ 그림 3] Local Variable Section 에서의 Method Parameter testmethod 는 10 개의 Parameter 변수를가진다. Local Variable Section 에서는그림 6 과같이할당받게된다. 여기서눈여겨봐야할것은 long 형과 double 형의경우 array 를두개씩사용한다는것이다. char, byte, short, boolean 형으로선언한것은 Local Variable Section 에는모두 int 형으로할당된다는것이다. 만약변수를선언할때 Inteager 형과 int 형중어느것이성능에더유리할것인가? int 형이성능에더유리하다그이유는 int 형은 Java Virtual Machine Stack 에저장되는반면 Inteager 형은 Heap 에저장이되기때문에 (reference) Heap 까지찾아가는비용이더들게되기때문이다. 0 번 Entry 의 hidden this 는선언한적이없는변수임에도불구하고 0 번 Entry 에저장이되어 있다. Hidden this 는 Heap 에있는 Class 의 Instance 에대한 reference 이다. Part 2 APM 453
Operand Stack Operand Stack 은 JVM 의작업공간이다. 그이유는 JVM 이연산에필요한데이터와연산결과를 Operand Stack 에넣고처리하기때문이다. 작동방식은하나의 Instruction 이연산을위해 Operand Stack 에값을넣으면다음 Instruction 에서는이값을빼서사용하게된다. 연산의결과역시 Operand Stack 에저장된다. Operand Stack 역시 Array 로구성되어있으며 Stack 의구조로 Push, Pop 작업을수행한다. Frame Data Stack Frame 을구성하고있는영역이다. 이곳에서는 Constant Pool Resolution 정보와 Method 가정상종료했을때의정보또는비정상종료를했을때발생하는 Exception 정보를저장하고있다. Resolution 이란 Symbolic Reference 를 JVM 에서실제접근할수있는 Direct Reference 로변경하는것을말한다. Symbolic Reference 는 Method Area 의 Constant Pool 에저장된다. Frame Data 에저장된 Constant Pool Resolution 은 Method Area 의 Constant Pool 의 Pointer 이다. JVM 은필요할때마다 Pointer 로 Constant Pool 에접근한다. 보통상수뿐만아니라다른 Class 를참조하거나, Method 를접근할경우에도 Constant Pool 을참조해야한다. 이는 Java 의모든 Reference 과 Symbolic Reference 인것과관련이있다. Method 가수행이되고종료하는시점에 Java Virtual Machine Stack 에서해당 Stack Frame 이 Pop 되어사라진다. 이때이전에 Method 를찾아가야하는데 Frame Data 에는이전에자신 을호출한 Stack Frame 의 Instruction Pointer 가들어가있다. 만약 Method 가 exception 을발생시키면해당 exception 을핸들링해줘야하는데이 exception 정보가 Frame Data 에저장이된다. Native Method Stacks 454 2013 기술백서 White Paper
JVM 은 Native Method 를위해 Native Method Stack 이라는메모리공간을가진다. Application 에서 Native Method 를호출하게되면 Native Method Stack 에새로운 Stack Frame 을생성하여 Push 한다. 이는 JNI 를이용해 JVM 내부에영향을주지않기위함이다. Native Method 의수행이끝나면해당 Method 를호출한 Stack Frame 이아닌새로운 Stack Frame 을하나생성하여작업을수행한다. [ 그림 4] Native Method 수행과 Stack 우리가자주사용하는 Hotspot JVM 이나 IBM JVM 에서는두 Stack 영역을구분두지않는다. 모두 Native Stack 으로통합이되어있는데이는 JVM 에서사용하는 Thread 가 Native Thread 인것과관계가깊다. Hotspot JVM 에서 Stack Size 를조정하는옵션은 Xss 와 Xoss 두가지인데, -Xss 는 Native Stack Size 를조정하는옵션이고 Xoss 는 Stack Size 를조정하는옵션이다. Hotspot JVM 에서 Stack Size 조정은 -Xss 만을통해서하도록되어있다. Part 2 APM 455
Method Area Method Area 는모든 Thread 가공유하는메모리영역이다. Method Area 는 Class 와 Interface 의 Bytecode 및메타데이터가저장이된다. 이는 Gabage Collection 의대상이되며 Hotspot JVM 의경우 Permenent Area 라는명칭으로사용된다. IBM JVM 같은경우는 Heap 내에 Class Object 형태로저장된다. Constant Pool Constant Pool 은 JVM 에서가장중요한역할을수행하는곳이고많이사용되는곳이기도하다. Constant Pool 에는 Literal Constant 는물론이고 Filed(Member Variable, Class Variable), Method 로의모든 Symbolic Reference 까지가진다. Symbolic Reference 의역할을하는곳이 Constant Pool 이다. Field Information Field Information 은모든 Field 의정보가있다. Field 이름 Field 의 Data Type, 선언순서 public, private 와같은 Field 의 Modifier Method Information Method Information 은모든 Method 정보를갖게된다. Method 이름, Method 반환값의 Data Type 과 void Method parameter 수와 Data Type, 선언순서, Method 의 Modifier 456 2013 기술백서 White Paper
만약 Method 가 native 나 abstract 가아니라면다음의정보가추가된다. Method 의 Bytecode Method Stack Frame 의 Operand Stack 및 Local Variable Section 의크기 Exception Table Class Variable Class Variable 은 static 으로선언한변수이며 Method Area 에저장된다. 이변수는모든 Instance 에서접근가능하기때문에동기화이슈가발생할수있다. Class Variable 을 final 로선언할경우이는 Constant Pool 에 Literal Constant 로저장된다. Method Table Method Area 에저장되는정보는 Heap 에 Object 를생성할때사용되기도하나 Reference 를위한 Data 로서의역할도중요하다. Java 에서는 Reference 로객체를찾아다니는일은속도측면에서굉장히중요하다. Method Table 은 Class 의 Method 에대한 Direct Reference 를가진다고보면된다. Method Table 을이용해 Super Class 에서상속된 Method 의 Reference 까지확인이가능하다. Java Heap Java Heap 에서많은성능이슈가발생하고있다. Gabage Collection 에의한것이대표적이예이다. Java Heap 은 Instance 와 Array 객체두종류가저장되는공간이다. Java Heap 은모든 Thread 에의해공유된다고했는데그로인해동기화문제가발생할수있다. Java Heap 은 Gabage Collection 이란 Mechanism 에의해메모리해제작업은필요하지않다. 실제많이사용하고있는 Hotspot JVM 과 IBM JVM 의 Object 의구조를살펴보자. Part 2 APM 457
Object 구조 Heap 에저장되는 Object 와 Array 객체는 Head 와 Data 로나뉘게된다. Hotspot Object 구조 Hotspot JVM 의 Object 의경우두개의 Header 를가지고있고, Array 객체의경우세개의 Header 를갖는다. [ 그림 5] HotSpot Object 구조 First header 는 Mark Word 라불리며 Gabage Collection 과 Syncronization 작업을위해사용한다. 두번째 Header 에는 Method Area 의 Class 정보를가리키는 Reference 정보가저장된다. Array 의경우세번째 Header 가존재하게되는데 Array Size 정보를갖기위한공간이다. IBM Object 구조 IBM JVM 은 Java 5 의경우를살펴보겠다. Object 의경우 2 개의 Header 를가지고 Array 의 경우 Array Size 정보를담고있는 Header 를포함해총 3 개의 Header 를가지게된다. 458 2013 기술백서 White Paper
[ 그림 6] IBM Object 구조 (java 5) Vtable 은 Object Information 에대한 Vtable Pointer 를가지고있고이는주로 Garbage Collector 에의해사용된다. 두번째 Header 는 Lock Word 를이용해 Object 의 Lock 획득유 무를확인하기위해사용된다. Heap 의구조 Hotspot JVM Heap 구조 Hotspot Heap 의가장큰특징은 Young Generation 과 Old Generation 으로나뉘어진다는 것이다. [ 그림 7] Hotspot JVM 의 Heap 구조 Part 2 APM 459
Young Generation 은 Eden 과 Survivor 영역으로구성되어있고최초 Heap 에객체가할당되는곳은 Eden 이다. 그이후 Object 참조여부를확인해서참조가되어있는상태면 Survivor 영역으로넘기고오래살아남으면 Old 영역으로이동시킨다. 이를 Promotion 이라고한다. 참고로 Young Generation 에서일어나는 GC 를 Minor GC 라고하고 Old Generation 에서일어나는 GC 를 Major GC 라고한다. IBM JVM Heap 구조 IBM JVM Heap 은버전에따라다른모습을보이고있다. 먼저 IBM JVM 1.4 를살펴보도록하 겠다. 1.4 버전의대표적특징은 One-Heap 이라는점이다. [ 그림 8] IBM JVM 1.4 Heap 구조 K Cluster 와 P Cluster 는 Hotspot JVM 의 Permanent Area 와같은역할을한다고보면된다. K Cluster 가 Method Area 의정보를가지고있는 Class Object 를저장하는공간인반면 P Cluster 는 Pinned 상태의 Array 나일반 Ojbect 를저장한다. Cache 영역은 Thread 마다 Lock 없이할당할수있는공간이다. LOA 는 Large Object 를위한공간이다. 이 Heap 은 Garbage Collection 과객체에빠른할당을하기위해 Allocbits 와 Markbits 라는 Bit Vector 와 Freelist 를가진다. 460 2013 기술백서 White Paper
[ 그림 9] Heap 과 Allocbits, Markbits, Freelist Allocbits 는 Object 의시작점에 Bit 가 On 이된다. Allocbits 는단순히할당여부만알수있고 Garbage Collection 의대상인지는판단할수없다. Object 의 Live 는 Markbits 를통해알수있다. Cache Alloction 을사용하여 Thread 가 Object 를할당할경우는 Thread 에게할당된 Heap(TLH) 을모두사용한후에나 Allocbits 에 On 으로표시된다. 그리고 Garbage Collection 에의해 Free space 가되면다시 Off 로된다. Freelist 는 Object 를위해 Heap 공간을할당하기위한자료구조로보면된다. 이 Freelist 는 linked List 구조로되어있으며마지막 Chunk 의 Next Filed 는 Null 이다. Object 에 Heap 을할당하기위해 Freelist 를탐색하고맞는 Chunk 가없으면다음 Free Chunk 를찾을때까지 Jump 를반복하게된다. 이때사용하고남은 Chunk 역시 Freelist 로등록되고만약 Chunk 의 Size 가 512 Byte 미만이면이는 Compaction 의대상이된다. 이렇게작은 Free Chunk 를 Dark Matter 라고한다. 1.4 버전부터 sub pool 을제공하는데이는 Freelist 를크기별로다양하게제공하는장점있다. 기존방법이 First Fit 이었다면 sub pool 방식은 Best Fit 을추구한다. IBM JAVA 5 Heap 구조 JAVA 5 에서는기존에버전과달리두가지변화가생긴다. 하나는 System Heap 을포함하지않는다는것이고다른하나는 Hotspot JVM 과같이 Generation Heap 을사용할수있다는것이다. 단옵션을적용할때만사용이가능하다. 옵션은다음과같다. Part 2 APM 461
-Xgcpolicy:gencon Hotspot JVM 에서 Young Generation 은 Nursery Generation 이고, Old Generation 은 Tenured Generation 이다 [ 그림 10] IBM JAVA 5 의 Generational Heap Nursery Area 는 Allocation Space 와 Survivor Space 로나뉘게되는데, Allocation Space 는 Object 가최초로할당되는곳이고 Survivor Space 는 Allocation Space 가가득차거나 Allocation Failure 가발생하면이동되는곳이다. Tenured Space 는 Nersery Generation 의성숙한 Object 들이 Promotion 하는곳이다. 결론 Runtime Data Areas 는객체의생성과소멸이반복되는곳이다. 그로인해성능이슈가빈번한곳이기도하다. 지금껏 Runtime Data Areas 에대해서알아보았는데이는성능분석을위한기초가될것이라고생각한다. 앞서살펴보았듯이하나를참조를위해 Java Stack, Method Area, Heap 의전부분에 Jump 작업을수행한다는것을알고있을것이다. 불필요한 Reference 의남발은성능을떨어뜨리는결과를만든다. 또한불필요하게 Method 의 Depth 역시깊어지게되어 Java Stack 에서는 Stack Frame 을더많이생성해야되고그에따라 push, pop 작업이빈번해진다. 이렇게 Stack Frame 이많아지는것역시모두 Resource 낭비로이어지게된다. 객체와 Primitive Type 차이가좋은예가될것이다. 앞으로 Runtime Data Areas 지식을바탕으로공부해나간다면 WAS 성능전문가의길도그리멀지만은않을것이다. 462 2013 기술백서 White Paper