450│2013 기술백서 White Paper 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
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
450│2013 기술백서 White Paper
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
Part 2 APM │451
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
452│2013 기술백서 White Paper
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; }
Part 2 APM │453
[그림 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이다.
454│2013 기술백서 White Paper
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
Part 2 APM │455
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는