1. JVM이란?
•
JVM - Java Virtual Machine
◦
Virtual의 의미
▪
JVM은 물리적인 형태가 아닌 소프트웨어로서 하나의 개념으로 존재한다.
◦
Machine의 의미
▪
JVM은 독자적으로 작동할 수 있는 메커니즘과 구조를 가지고 있다.
▪
하나의 v축약된 컴퓨터와 같은 의미다.
•
JVM이 구체적으로 무엇이냐는 질문에 정확한 정의를 내린다기 보다는 하나의 개념, 스펙에 지나지 않는다.
◦
어느 누구도 정확하고 자세한 설계도를 제공하지 않는다.
◦
표준화된 정의만이 존재할 뿐이다.
◦
각 JVM 벤더들은 표준에 맞도록 자신의 JVM을 별도로 구현한다.
•
즉 JVM은 정의된 스펙을 구현한 하나의 독자적인 프로세스 형태로 구동되는 Runtime Instance라고 할 수 있다.
그림1
•
Class Loader
◦
JVM 내로 class파일들을 Load 하여 Loading된 클래스들을 Runtime Data Area에 배치
•
Execution Engine
◦
Loading된 클래스의 Bytecode를 해석
•
Runtime Data Areas
◦
JVM이라는 프로세스가 프로그램을 수행하기 위해 OS에서 할당받은 메모리 공간
JVM 아키텍처
•
Method Area
◦
클래스, 변수, 메소드, static 변수, 상수 정보 등이 저장되는 영역
•
Heap Area
◦
new 명령어로 생성된 인스턴스와 객체가 저장되는 구역
•
Stack Area
◦
Method 내에서 사용되는 값들(매개변수, 지역변수, 리턴값 등)이 저장되는 구역
◦
메소드 호출시마다 메모리에 LIFO로 생성/삭제된다.
•
PC Register
◦
PC 레지스터와 역할이 비슷하고, JVM 명령의 주소값이 저장된다.
•
Native Method Stack
◦
다른 언어(C/C++ 등)의 메소드 호출을 위해 할당되는 구역으로 얼어에 맞게 Stack이 형성되는 구조
1.2 Java Heap
•
Java의 Heap영역은 메모리 자동해제, 즉 GC(Garbege Collection)과 연관이 깊다.
•
사람들이 자바의 메모리 구조는 곧 Heap이라 오해하지만, 여러 다른 메모리 영역도 존재한다.
•
Heap은 Instance와 Array객체 두 가지 종류만 저장되는 공간일 뿐이다.
•
Heap은 데이터가 공유되어 동기화 문제 이슈가 발생할 수 있다.
•
JVM은 Heap에 Memory를 할당하는 Instruction만 존재하고 메모리 해제를 위한 어던 Java Code나 Bytecode도 존재하지 않는다.
•
메모리 해제는 오직 GC를 통해서만 수행된다.
◦
이 또한 정해진 부분 없이 벤더마다 다를 수 있다.
1.2.1 Hotspot JVM의 Heap 구조
•
Young Generation은 Eden과 Survivor영역으로 구성된다.
◦
이 영역에서 일어나는 GC를 Minor GC라 말한다.
◦
Eden은 최초로 메모리에 할당되는 장소이며 꽉 차게 되면 참조 여부를 체크해 Live Object라면 Survivor영역으로 넘어가고 아니라면 GC에 의해 메모리에서 해제된다.
◦
Survivor영역은 말 그대로 살아남은 Object들이 잠시 머무르는 장소로 2개의 영역이 있지만 하나의 영역만을 사용한다.
•
Young Generation에서 오래 살아남은 객체는 Old Generation으로 이동된다.
◦
이 영역에서 일어나는 GC를 Full GC라고 한다.
◦
특정 회수 이상 참조되어 Age를 초과한 Object를 의미한다.
•
Perm 영역은 보통 Class의 Meta 정보나 Method의 Meta 정보, Static 변수와 상수 정보 등이 저장되는 공간으로 흔히 메타데이터 저장 영역이라고도 한다.
•
자바 8에서 JVM 메모리 구조적 개선사항으로 Perm 영역이 Metaspace영역으로 전환되어 Perm 영역은 사라지게 되었다.
◦
해당 Metaspace 영역은 Native 메모리에서 관리된다.
1.2.2 Java 8의 Metaspace 초기치와 최대치 확인
./java -XX:+PrintFlagsFinal -version -server | grep MetaspaceSize
Shell
복사
•
위 명령어를 실행하면 7버전의 경우 82MB, 8버전의 경우 16Exabyte라는 매우 큰 수치를 볼 수 있다.
◦
16ExaByte는 64Bit 프로세서가 취급할 수 있는 메모리 상한치다.
•
Metaspace 영역은 Native 메모리로 다루기 때문에 프로세스가 이용할 수 있는 메모리 자원을 최대한 활용할 수 잇다고 본다.
◦
그러나 이 메모리 크기도 별도의 옵션(MaxMetaspaceSize)을 통해 제한이 가능한다.
◦
Classloader에 메모리 누수가 의심될 경우 -XX:MaxMetaspaceSize를 지정할 필요가 있다고 본다.
•
Metaspace는 만능의 영역이 아니기 때문에 기존 발생한 메모리 누수가 완벽하게 해소되지는 않는 것으로 보인다.
◦
기존엔 메모리 누수가 의심되는 환경에서 Perm 영역의 상한값이 모종의 제한 역할을 했다.
◦
Metaspace 영역에서는 기본적으로 이 제한의 역할이 존재하지 않기 대문에 무한하게 메모리 영역이 확대될 수 있다.
•
Metaspace는 필요에 따라 자동적으로 메모리 상한치가 증가하기 때문에 일반적으로 크게 주의를 가지고 설정할 필요가 없다.
1.2.3 IBM JVM의 Heap 구조
IBM JVM의 Heap은 Java 1.4.X 이전과 Java 5 이후를 기준으로 달라진 부분이 있다.
•
1.4.2 까지는 System Heap과 Heap으로 구분되었으나 5부터는 이러한 구분이 사라졌다.
•
5부터는 GC의 설정에 따라 Generational Heap 구성이 가능해졌다.
•
5에 와서 IBM JVM의 Heap에서는 두 가지의 큰 변화가 있었다.
◦
System Heap을 더 이상 포함하지 않게 된 것
◦
Hotspot JVM과 같이 Generational Heap을 사용할 수 있게 된 것
•
GC옵션 중 Genetation Concurrent 옵션인 `-Xgcpolicy:gencon을 추가하고 JVM을 시작하면 아래 그림과 같은 형태의 Heap이 구성된다.
•
Hotspot JVM의 Young Generation역할을 하는게 Nursery Genetation이다.
◦
Object가 생성된지 얼마 되지 않아 Garbege가 되어 사라지는 것을 흔히 유아 사망률(Infant Mortality)이라 한다.
◦
이에 착안해 탁아소라는 명칭을 사용한듯 하다.
•
Nursery도 Allocate와 Survior 영역으로 나뉘게 된다.
◦
Allocate는 Object가 최초로 할당되는 곳이다.
◦
Survior은 Allocate 영역이 꽉 차거나 다른 이유로 인해 Allocate Failure이 발생하게 되면 Allocate영역의 Live Object를 대피시키는 곳이다.
◦
이 또한 GC의 과정이다.
•
Tenured 영역은 Nursery영역의 성숙한 Object들을 Promotion하는 곳이다.