
- 바이트코드는 JVM이 읽는 언어.
.class 파일과 바이트 코드 소개

- .java → compile → .class
- 자주 쓰이는 바이트 코드 → native머신 언어로 변형. 바이트코드 → 네이티브 코드 JIT
클래스 로더
- 이름을 알고 있는 특정 클래스에 대한 정의(Byte Stream)을 가져오는 역할 수행
- 부트스트랩 클래스 로더
- JVM에서 라이브러리로 취급(rt.jar, tools.jar)되는 것들을 로드 (핫스팟에서는 C++로 구현)
- 플랫폼 클래스 로더(기존 확장 클래스 로더)
- 클래스 라이브러리 로드
- 애플리케이션 클래스 로더
- sum.misc.Launcher$AppClassLoader 의미
클래스 로더 별 담당 모듈(일부)
- Bootstrap
- java.base
- java.desktop
- java.logging
- java.naming
- java.net
- java.sctp
- Platform
- java.compiler*
- java.cobar*
- java.sql
- java.charset
- java.jsobjdct
- java.security.auth
- java.xml.dom
- Application
- jdk.complier
- jdk.hotspot.agent
- jdk.jartool
- jdk.jcmd
- jdk.jshell
- jdk.pack
compile → link → runtime
Java 클래스 로딩
- 클래스 로딩 및 링킹 과정이 모두 런타임에 이루어짐
- 실행 성능이 일부 저하될 수 있으나 높은 확장성과 유연성을 제공하는 근간
- 인터페이스만 맞으면 Runtime에 구현 클래스를 결정하지 않을 수 있음
- 클래스 로더는 실행할 프로그램 코드를 네트워크로 수신하는 것도 가능
- 해석(Resolution) 단계는 동적 바인딩(혹은 늦은 바인딩)을 지원할 목적으로 초기화 후로 지연될 수 있음
클래스 검증
- JVM 명세가 정하는 규칙, 제약을 만족하는지 확인
- 파일 형식(.class)
- 메타데이터
- 바이트코드
- 심벌 참조
- 보안위협에 대한 검증 포함
- 바이트코드 검증 시 함께 확인
준비 및 해석
- java.lang.Class 인스턴스(메타 데이터)가 힙 영역에 생성되고 클래스 변수(정적 멤버) 메모리를 0으로 초기화
- 로드되는 클래스의 인스턴스는 Using 단계에서 힙 사용
- final 선언된 변수는 코드에서 정의한 초깃값으로 정의(0이 아닐 수 있음)
- 생성자 호출 전 상태(new 연산 전)
- 필드(인스턴스 변수) 초깃값은 생성자 호출 시 정의
- 정적 필드에 초깃값 할당
- 해석은 상수 풀의 심벌 참조를 직접 참조로 대체하는 과정
Heap 영역에 객체 생성
- JVM은 객체 저장을 위한 메모리 공간 확보 후 0으로 초기화(단, 객체 헤더 제외)
- 객체 초기화 위한 구성 설정 실시
- 클래스 이름 및 메타 정보 확인 방법
- 객체에 대한 해시코드
- GC 세대 나이
- 생성자 호출

JVM runtime data area

Method area(Runtime constant pool)
- JVM이 읽어 들인 각종 타입 정보, 상수, 정적(static) 변수 정보가 저장되는 영역
- JIT(Just In Time) 컴파일러가 번역한 기계어 코드를 개싱하기 위한 메모리 공간으로 활용
- Java 8 부터는 PermGen이 아니라 Metatspace에 속함.
- Metaspace는 JVM 힙이 아니라 네이티브 메모리에서 관리하며, 크기가 동적으로 달라질 수 있음
Runtime constant pool
- 클래스 버전, 필드, 메서드, 인터페이스 등 클래스 파일에 포함된 정보 및 각종 리터럴, 심볼 참조가 저장되는 영역
- 클래스 로더가 클래스 로드할 때 상기 정보들을 저장
- 동적으로 운영되며 런타임에 새로운 상수 추가될 수 있음
Stack area
- 지역 변수 테이블, 피연산자 스택, 메서드 반환값 등 저장
- C/C++의 스택보다 더 복잡한 구조
- 보통 지역변수 테이블을 스택으로 지칭
- 지역변수 테이블은 슬롯으로 이뤄지며 기본형 변수 하나가 슬론 한개(혹은 2개) 사용
- Java 스택의 크기는 메모리 용량이 아닌 슬롯의 개수
- JVM이 허용하는 스택의 크기 초과 시, StackOverflowError 발생

Native method stack
- C++로 개발된 Native 코드(함수 단위)가 실행 될 때 지역변수 및 자동변수가 사용하는 스택 메모리
- 구현하기에 따라 JVM stack과 합쳐서 사용하기도함
JVM Heap 영역
- GC가 관리하는 메모리 영역
- Java에서 사용되는 객체의 인스턴스 및 배열이 저장되는 공간
- 설정에 따라 크기를 변경하거나 고정할 수 있음
- 부족시 OutOfMemoryError 발생
- 세대별 컬렉션 이론(Generational Collection Theory)을 기반으로 설계 및 운영
- Eden, Survivor
- New/Old generation
- 영구 세대(Metaspace)
JVM GC
- Heap 에서 참조되지 않는 개체를 수집 및 제거해 메모리 회수
- Minor/Major(Full) GC
- GC 수행 시 프로그램 일시 정지
- stop the world
- GC 속도
- Minor GC가 보통 1초 이내 완료
- Full GC는 수 초 이상 진행되기도 하며 이 지연 때문에 DB연결이 끊기는 등 운영문제 발생할 수 있음
GC 기술의 시작
- Java에서 거의 모든 인스턴스는 힙에 저장
- GC는 1960년대 만들어진 리스프
- GC가 처리해야할 문제의 핵심 3요소(by 리스프 창시자 존 맥카시)
- 회수 대상 메모리 판단
- 메모리 회수 시점
- (구체적인) 메모리 회수 방법
