JVM은 Runtime Data Area(실행 데이터 영역)으로 불리며 여러 영역으로 분리되어 있다.
1. 프로그램 실행 시 JVM은 OS로부터 메모리를 할당
2. 자바 컴파일러(javac)가 자바 소스코드(.java)를 자바 바이트코드(.class)로 컴파일
3. Class Loader를 통해 JVM Runtime Data Area로 로딩
4. 로더에 의하여 로딩 된 .class들은 Execution Engine을 통해 Interpret(해석)
5. 해석된 바이트 코드는 Runtime Data Area의 각 영역에 배치되어 수행
이 과정에서 Execution Engine에 의해 GC의 작동과 쓰레드 동기화가 이루어짐
모든 Thread 공유
개별 Thread 할당
JVM Language Stacks
Local Variable, Prameter, 메소드 정보, 임시데이터가 저장
JVM은 스택 프레임을 Push/Pop하는 연산만 수행
printStackTrace()를 통해 Stack Trace로 각 스택 프레임을 출력
PC Registers
스레드가 시작될 때 생성
스레드의 명령어 실행을 기록, JVM의 명령어 주소를 가짐
Native Method Area
바이트 코드가 아닌 Binary Code 실행 영역
JNI(Java Native Interface)를 통해 호출되는 C/C++의 코드를 실행하는 영역
(I/O작업을 위한 C 라이브러리 함수 등)
자바의 경우 GC로 인하여 약간 특이한 Heap 영역을 가지고 있다.
Stack Space
Heap Space
nullPointerException 참고
Calling the instance method of a null object.
(빈 객체의 메소드를 호출하는 경우)
Accessing or modifying the field of a null object.
(빈 객체의 필드에 접근하거나 수정하려는 경우)
Taking the length of null as if it were an array.
(빈 배열의 길이를 가져오려는 경우)
Accessing or modifying the slots of null as if it were an array.
(빈 배열의 인덱스를 접근하거나 수정하려는 경우)
Throwing null as if it were a Throwable value.
(예외처리를 위해 널 값을 던지는 경우)
힙 영역 구조
Eden과 Survior로 이루어진 Young Generation (젊은 세대)
참조가 거의 없는 Old, 프로그램 종료 시까지 살아있어야하는 메타데이터 집합인 Permanent
Young Generation
Eden
new를 통해 새로 생성된 객체가 위치
정기적인 쓰레기 수집 후 살아남은 객체들은 Survivor로 이동
Survivor1, Survivor2
각 영역이 채워지게 되면, 살아남은 객체는 비워진 Survivor로 이동
이때 참조가 없는 객체들은 Minor GC로 수집 됨
따라서, 항상 Survivor1과 2중 한 곳은 비어있는 상태
Minor GC
Eden, Survivor에서 발생하는 GC
Old
Youn Generation에서 마지막까지 살아남은 객체가 이동
Major GC가 이루어지며, Minor GC보다 횟수가 적음
Major GC
Old, Permanent 영역에서 발생하는 GC
Permanent
Class Loader에 의해 Load된 클래스들이 저장
JDK 8부터는 Metaspace 영역으로 교체
Youn Generation의 Minor GC, Old의 Major GC를 거치며 최종적으로 모든 쓰레기가 수집
Process Memory Layout
메모리 영역, 정적/동적 메모리 할당
자바 메모리 관리
Java Call Stack
JVM 메모리 구조
java-stack-heap
JVM 메모리 구조