runtime data areas - amazon s3 · 2015-10-21 · runtime data areas ㈜엑셈...

13
4502013 기술백서 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

Upload: others

Post on 26-Jun-2020

8 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Runtime Data Areas - Amazon S3 · 2015-10-21 · Runtime Data Areas ㈜엑셈 컨설팅본부/APM팀 임 대호 Runtime Data Area 구조 Runtime Data Area는 JVM이 프로그램을

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

Page 2: Runtime Data Areas - Amazon S3 · 2015-10-21 · Runtime Data Areas ㈜엑셈 컨설팅본부/APM팀 임 대호 Runtime Data Area 구조 Runtime Data Area는 JVM이 프로그램을

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

Page 3: Runtime Data Areas - Amazon S3 · 2015-10-21 · Runtime Data Areas ㈜엑셈 컨설팅본부/APM팀 임 대호 Runtime Data Area 구조 Runtime Data Area는 JVM이 프로그램을

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; }

Page 4: Runtime Data Areas - Amazon S3 · 2015-10-21 · Runtime Data Areas ㈜엑셈 컨설팅본부/APM팀 임 대호 Runtime Data Area 구조 Runtime Data Area는 JVM이 프로그램을

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이다.

Page 5: Runtime Data Areas - Amazon S3 · 2015-10-21 · Runtime Data Areas ㈜엑셈 컨설팅본부/APM팀 임 대호 Runtime Data Area 구조 Runtime Data Area는 JVM이 프로그램을

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

Page 6: Runtime Data Areas - Amazon S3 · 2015-10-21 · Runtime Data Areas ㈜엑셈 컨설팅본부/APM팀 임 대호 Runtime Data Area 구조 Runtime Data Area는 JVM이 프로그램을

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는

Native Stack Size 를 조정하는 옵션이고 –Xoss는 Stack Size를 조정하는 옵션이다. Hotspot

JVM에서 Stack Size 조정은 -Xss만을 통해서 하도록 되어 있다.

Page 7: Runtime Data Areas - Amazon S3 · 2015-10-21 · Runtime Data Areas ㈜엑셈 컨설팅본부/APM팀 임 대호 Runtime Data Area 구조 Runtime Data Area는 JVM이 프로그램을

456│2013 기술백서 White Paper

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

Page 8: Runtime Data Areas - Amazon S3 · 2015-10-21 · Runtime Data Areas ㈜엑셈 컨설팅본부/APM팀 임 대호 Runtime Data Area 구조 Runtime Data Area는 JVM이 프로그램을

Part 2 APM │457

만약 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의 구조를 살펴보자.

Page 9: Runtime Data Areas - Amazon S3 · 2015-10-21 · Runtime Data Areas ㈜엑셈 컨설팅본부/APM팀 임 대호 Runtime Data Area 구조 Runtime Data Area는 JVM이 프로그램을

458│2013 기술백서 White Paper

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를 가지게 된다.

Page 10: Runtime Data Areas - Amazon S3 · 2015-10-21 · Runtime Data Areas ㈜엑셈 컨설팅본부/APM팀 임 대호 Runtime Data Area 구조 Runtime Data Area는 JVM이 프로그램을

Part 2 APM │459

[그림 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 구조

Page 11: Runtime Data Areas - Amazon S3 · 2015-10-21 · Runtime Data Areas ㈜엑셈 컨설팅본부/APM팀 임 대호 Runtime Data Area 구조 Runtime Data Area는 JVM이 프로그램을

460│2013 기술백서 White Paper

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

를 가진다.

Page 12: Runtime Data Areas - Amazon S3 · 2015-10-21 · Runtime Data Areas ㈜엑셈 컨설팅본부/APM팀 임 대호 Runtime Data Area 구조 Runtime Data Area는 JVM이 프로그램을

Part 2 APM │461

[그림 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 을 사용할 수 있다는 것

이다. 단 옵션을 적용할 때만 사용이 가능하다. 옵션은 다음과 같다.

Page 13: Runtime Data Areas - Amazon S3 · 2015-10-21 · Runtime Data Areas ㈜엑셈 컨설팅본부/APM팀 임 대호 Runtime Data Area 구조 Runtime Data Area는 JVM이 프로그램을

462│2013 기술백서 White Paper

-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 성능 전문가의 길도 그리 멀지만은 않을 것이다.