jvm은 여러 구현체가 존재한다.
따라서, 벤더 업체마다 상이한 구현 철학?매커니즘?이 적용되어있다.
대표적으로, jvm은 Stack-based or Register-based 방식인데,
대부분이 전자로 구현되어있다고 한다. 글 또한 전자를 바탕으로 한다.

javac
컴파일 수행 (.java -> .class)
-- class loader --
1. loading : .class를 jvm에 로드
2. linking :
2-1. verifying : jvm 명세 준수 검증
2-2. preparing : 메모리 할당
2-3. resolving : 심볼릭 레퍼런스를 다이렉트 레퍼런스로 변경
3. initialization : 클래스 변수 초기화 (static 선언 포함)
-- excution engine --
GC + [interpreter, JIT Compiler 혼합 사용]
interpreter
명령어를 하나씩 읽고 해석하여 실행하는 방식 사용
(하나란 단일 op code를 의미, code line이 아님)
기본적으로 해당 방식으로 동작 (java는 interpreter 언어다.)
JIT(Just-In-Time) Compiler
byte code를 곧바로 native code로 변경
이후 캐싱해 두었다가 native code로 직접 실행
전처리 비용이 있지만 특정 상황에 유리(e.g. 같은 메서드 매우 많이 호출)
jvm은 기본 interpreter로 동작, 전처리 비용을 감안해도 더 효율적일 때 jit compiler 사용
GC
heap 영역에서 사용하지 않을 것이라고 판단되는 메모리를 회수한다.
byte code 중간 변환과 더불어 c계열보다 java가 느린 이유다.
system.gc()로 직접 수행해도 실행이 보장되지 않는다.
-- runtime data area --
method(static) area
1. 클래스 메타데이터, 바이트코드 등
=> 주로 인스턴스화 되지 않은 고정 데이터 위치
2. JIT 컴파일러가 번역한 기계어 코드를 캐싱
Java 8부터는 PermGen -> Metaspace에 속함
rutime constant pool
method area에 포함 되지만 용도상 구분
1. method area 메타데이터로 인스턴스화된 객체의 시그니처 및 레퍼런스 저장
2. 리터럴 등 캐싱 데이터 저장 ("abc", 3.14, -128~127 (Integer 사용 시))
jvm이 런타임간 사용 - 레퍼런스를 조회하여 실제 메모리에 접근
heap area
1.대부분의 동적 할당 데이터 저장 (레퍼런스 타입)
e.g. 인터페이스, 클래스(new 키워드 및 익명 클래스 포함), 배열, String
2. 정적(static) 메서드와 변수 저장
plus
1.
문자열을 리터럴로 선언하면 method area 안의 rutime constant pool 안의 string constant pool에 저장
(리터럴의 불변성을 통해 메모리 최적화 e.g. 중복 제거)
문자열을 new String 키워드로 선언하면 heap area에 저장
String.intern()으로 string constant pool에 저장 가능
2.
모든 클래스는 명시하지 않아도 object를 extends한다.
명시적 extends하면, 이미 되어있으므로 경고 (in intellij)
Class 'YOUR_CLASS' explicitly extends 'java.lang.Object'
stack area
주로 블럭 혹은 프레임 단위({...})에 할당되는 정보 저장
지역 변수, 연산 임시 값 등
멀티 스레드 사용 시, 공유되지 않고 스레드별로 고유 stack 존재
native method stack
타 언어를 위한 메모리 공간
PC Register (Program Counter Register)
java byte code 수준에서, 명령어 순서/흐름 제어를 위한 순번과 정보 저장
tmi) Stack-based jvm도 어느 정도는 Register-based인 대표 요소라고 함
멀티 스레드 사용 시,
stack area
native method stack
PC Register
는 각 스레드마다 독립적인 공간을 할당한다. (n개 스레드면, 각 n개 필요)
javac, javap는 각각 javac.exe, javap.exe를 실행시키는 명령어이며,
터미널에서 이를 통해 java byte code 생성, 디스어셈블링한 출력 조회를 할 수 있다.
이 외 cmd 조회 명령어(옵션제외)
# 힙 영역
jmap -heap <PID>
# 스택 영역
jstack <PID>
# gc
jstat -gc <PID> 1000 # 모니터링 주기 지정 (millis, 현재 1초)
# jvm 전체
jconsole