JVM
- sw로 cpu도 구현되어있고, 가상메모리(ram+ssd) + OS
- cs이론에서 os랑 컴퓨터구조론에 포함되는 이론을 믹스해서 이를 C나 C++로 구현을하면 JVM이 되는 것이다. 매우 심오하단 얘기다.
- 자바는 가상머신 상태라서 app이 잘못된다고 해서 os가 다운되는 일이 절대 없다. (보안성이 뛰어남)
- 즉, 바이트 코드로 잘 짜주기만 한다면 os가 무엇이 되었든 잘 작동하는 장점이 있다.
Java, C++ 메모리 관리 차이
C++
- 객체에 대한 모든 관리 책임은 개발자에게 있음.
(자유도가 높다는 말, 그러나 책임을 모두 개발자가 짊어지게 된다)
- 객체의 생명주기에 모두 개입하는 구조.
Java
- 개체 메모리 해제는 전적으로 JVM의 몫
- 개발자에게는 소유권도 책임도 없다
- 문제 발생 시 구조를 알아야 대응이 가능
C++은 자취방에서 음식을 해먹거나 시켜먹는 느낌. 즉, 자율적으로 본인이 먹고 접시를 치우면 되는 느낌이다. But Java는 뷔페에 가서 먹고 싶은 음식을 가져온 후 퇴식구에 그릇만 두면 알아서 일하는 직원들이 치워준다. (가비지 컬렉터)
native 영역이란 무엇일까 ?
JVM 구성요소
JVM은 Process다.

시점이 중요하다
1. 컴파일
2. 링크
3. 실행(런타임)
실행하고 링크 이 두가지를 담당해주는 요소가 '클래스 로더'다.
(자바는 컴파일/링크+실행 으로 나눠져 있다)
우리가 객체를 new + ' ' 하면서 인스턴스를 동적 생성한다.
그럼 이 인스턴스가 저장되는 영역은 어디일까?
-> heap Area.
메서드 함수는 ?
-> Method Area
문자열 상수는?
-> runtime constant pool
뭐 이런식으로 돌아가는 것이다.

클래스 로더
jvm을 이용해서 java 바이트 코드를 구동시켜 줄 수 있는 프로그래밍 언어가 자바만 있는 것이 아니라 코틀린 등등이 있다. (얘네들도 다 자바 byte코드로 번역해줌)
- 이름을 알고 있는 특정 클래스에 대한 정의(Byte stream)를 가져오는 역할을 수행
=> 정의란, byte 코드를 가져온다고 이해하면 되는거.
- 부트스트랩 클래스 로더
- jvm에서 라이브러리로 취급(et.jar, tools.jar)되는 것들을 로드 (핫스팟에서는 C++로 구현)
- 플랫폼 클래스 로더 (기존 확장 클래스 로더)
- 클래스 라이브러리 로드
- 애플리케이션 클래스 로더
- sun.misc.Launcher$AppClassLoader를 의미

출처 : 널널한 개발자
Java 클래스 로딩
- 클래스 로딩 및 링킹 과정이 모두 런타임에 이뤄짐
- 실행 성능이 일부 저하될 수 있으나 높은 확장성과 유연성을 제공하는 근간이다.
- 인터페이스만 맞으면 Runtime에 구현 클래스를 결정하지 않을 수 있따.
- 클래스 로더는 실행할 프로그램 코드를 네트워크로 수신하는 것도 가능
- 해석(Resolution)단계는 동적 바인딩(혹은 늦은 바인딩)을 지원할 목적으로 초기화 후로 지연될 수 있음.
클래스 검증
(시간이 많아짐, 런타임 저하, 성능 저하 -> but 보안에 너무 좋음)
- jvm 명세가 정하는 규칙과 제약을 만족하는지 확인
- 파일 형식(.class)
- 메타 데이터
- 바이트 코드
- 심벌 참조
- 보안위협에 대한 검증 포함
- 바이트코드 검증 시 함께 확인
준비 및 해석
- 객체 인스턴스가 저장될 메모리 공간을 확보하고 0으로 초기화
- 생성자 호출 전 상태(필드 초깃값은 생성자 호출 시 변경)
- 단, 심볼릭 상수 필드는 값을 할당
- 해석은 상수 풀의 심벌 참조를 직접 참조로 대체하는 과정
(직접 참조는 어떤 함수를 호출할 때, 저장되어있는 메모리 위치를 직접 찾아내는 것이 직접 참조이. 그런데 이 과정에서 바인딩이 정확하게 되는 것이고, 대체하는 과정이 해석이다)
Heap 영역에 객체생성
사실 여기에 제일 중요한 것은 meta데이터 영역이라고 생각한다.
가바지 컬렉터 등등 중요한건 여기에 다 있기 때문이다.
강의에선 heap 영역 안에 메타데이터가 있다고 말씀하신 것 같은데 (맞나..?)
아무튼!, 두 영역은 서로 독립적이며, 메타 데이터 영역은 JVM 메모리 구조에서 별개의 영역입니다. 자바 8을 기준으로 분리되었기 때문입니다.
- jvm은 객체 저장을 위한 메모리 공간을 확보 후 0으로 초기화(단, 객체 헤더 제외)
- 객체 초기화를 위한 구성설정 실시
- 클래스 이름 및 메타 정보 확인 방법
- 객체에 대한 해시코드
- GC세데 나이
- 생성자 호출
해시코드에서 해시는 무엇일까? 그리고 해시코드란 무엇인가 ?
- 해시는 데이터를 고정된 길이의 값으로 변환하는 기술이고, 해시코드는 Java 객체를 빠르게 식별하기 위한 고유한 정수 값이다.
사실 해시와 해시코드에 대해 설명하려면 정말 길다.
이 부분은 다른 포스트를 통해서 공유하도록 하겠습니다.

런타임 데이터 영역
프로그램 카운터 레지스터 PCregister를 주의깊게 봐야한다.
그렇다면, 이것은 무엇일까?
JVM의 각 Thread가 현재 어느 부부의 명령어를 실행 중인지 기록하는 영역
PC Register의 주요 역할
- 명령어 위치 저장
- 현재 실행 중인 바이트코드 명령어의 주소를 저장
- jvm이 어떤 명령을 실행해야 하는지 알기 위해 사용
- 스레드 독립적
- 각 스레드마다 독립적인 PC Register가 존재
- 스레드마다 수행 중인 명령어의 위치가 다를 수 있기 때문
- 메서드 구분
- 현재 실행 중인 메서드가 네이티브 메서드인지 일반 java 메서드인지 구분
- 네이티브 메서드를 실행할 경우, PC Register는 특정 명령어를 저장하지 않고 Undefinded 상태가 된다.
PC Register의 메모리 영역
- 메모리 크기: 매우 작다 (한 스레드당 하나의 PC Register만 존재).
- 저장 내용: JVM 명령어(Bytecode) 실행 위치.
- 생성 및 관리: 각 스레드가 생성될 때 자신의 PC Register를 생성.
PC Register와 JVM 스레드
- 멀티스레드 환경
- 각 스레드는 자신만의 PC Register를 가진다.
- 하나의 스레드가 실행 중인 메서드와 명령어 위치는 다른 스레드와 완전히 독립
- 명령어 포인터 역할
- JVM은 PC Register의 값에 따라 다음에 실행할 명령어를 확인.
- 실행이 끝나면 PC Register는 다음 명령어의 주소로 업데이트.
여기서 나는 질문이 생겼다.
"하나의 스레드가 실행 중인 메서드와 명령어 위치는 다른 스레드와 완전히 독립"
이라는 말은
"스레드마다 수행 중인 명령어의 위치가 다를 수 있기 때문"라고 정리 했는데,
-> ??? 이해를 못하는 중입니다.
포스팅 할 때 코드를 예시로 확인했었는데, 쓰레드는 작업단위이기 때문에 스레드마다 위치가 다를 수 있다는건가?? 이 부분 제대로 짚고 넘어갈 예정입니다.
(오늘 이해 못하면, 꼭 이해하고 다음 포스팅에 작성하겠습니다)
- 네이티브 메서드는 c, c++로 작성된 메서드, 자바 프로그램이 os나 hw와 직접 상호작용해야 할 때 사용된다.
한 줄 요약
각 스레드는 독립적인 실행 흐름을 가지기 때문에, JVM은 스레드마다 독립적인 PC Register를 제공해 실행 중인 명령어 위치를 추적한다.
Method area
(static)
- jvm이 읽어 들인 각종 타입 정보, 상수, 정적 변수가 정보가 저장되는 영역
- JIT(Just In Time)컴파일러가 번역한 기게어 코드를 캐싱하기 위한 메모리 공간으로 활용
- java8부터는 Metaspace에 속함
- Metaspace는 jvm 힙이 아니라 native 메모리에서 관리하며 크기가 동적으로 달라질 수 있다.
Runtime constant pool
(매우 중요)
- 클래스 버전, 필드, 메서드, 인터페이스 등
클래스 파일에 포함된 정보 및 각종 리터럴, 심볼 참조가 저장되는 영역
- 클래스 로더가 클래스를 로드할 때 상기 정보들을 저장
- 동적으로 운영되며 런타임에 새로운 상수가 추가될 수 있다
학습한 내용
런타임 상수 풀은 jvm에서 사용되는 메모리 영역으로, 클래스 파일(.class)의 상수 및 심볼릭 참조가 저장되는 공간이다.
- 클래스 로딩 단계에서 jvm의 메모리(runtime area)에 생성
- java의 string literal pool과 관련있음
- 주로 상수 값과 메서드, 필드, 클래스에 대한 참조 정보를 저장
java7 이하 : Method area 안에
java8 이상 : Metaspace 안에 (힙 밖, Native memory로 이동)
- 클래스 로딩 단계에서 jvm의 메모리(runtime area)에 어떻게 생성하는거지 ?
- java의 string literal pool과 어떻게 관련있지 ?
- 주로 상수 값과 메서드, 필드, 클래스에 대한 참조 정보를 어떻게 저장한단거지 ?
클래스 로딩
1. 클래스 로딩 단계에서 JVM 메모리(Runtime Area)에 어떻게 생성될까?
1.1 클래스 로딩 과정
클래스 로딩은 JVM이 클래스 파일(.class)을 읽고 메모리에 올리는 과정이다.
이 과정에서 Runtime Constant Pool이 생성된다.
클래스 로딩 단계 요약
- Loading (로딩)
.class
파일이 JVM에 의해 로드된다.
- ClassLoader가
.class
파일을 읽고, JVM 메모리(Runtime Area)에 클래스 메타 데이터를 로드한다.
- Linking (연결)
- Verification (검증):
.class
파일이 유효한지 확인
- Preparation (준비): 클래스 변수(static 필드) 메모리 할당 및 기본값 초기화
- Resolution (해결): 심볼릭 참조를 메모리 참조로 변환
- Initialization (초기화)
- 클래스 변수의 값을 초기화하고, static 블록이 실행된다.
Runtime Constant Pool 생성 시점
Loading 단계에서 .class
파일의 constant pool 테이블이 JVM 메모리의 Runtime Constant Pool로 복사된다.
1.2 Runtime Constant Pool의 구성 요소
클래스 파일 내의 Constant Pool Table에 있는 정보가 Runtime Constant Pool로 복사된다.
- 문자열 리터럴 (String Literal)
- 숫자 상수 (int, float, long 등)
- 심볼릭 참조 (클래스, 메서드, 필드 이름)
이때, String Literal
은 별도로 String Pool에 저장된다.
2. Java의 String Literal Pool과 Runtime Constant Pool의 관계
2.1 String Literal Pool이란?
String Literal Pool은 Runtime Constant Pool의 일부다.
문자열 리터럴은 Runtime Constant Pool에 저장되며, 효율성을 위해 String Pool에서 관리된다다.
2.2 String Literal의 동작 방식
(코드로 이해하면 쉬움)
String Pool과 Runtime Constant Pool의 관계
- String 리터럴은 Runtime Constant Pool의 일부로 저장되며, 메모리 절약 및 성능 최적화를 위해 String Pool에서 재사용된다.
3. Runtime Constant Pool의 중요성
- 메모리 절약 : 동일한 상수나 문자열 리터럴은 중복 저장되지 않고 공유
- 빠른 참조 : JVM은 Runtime Constant Pool에 저장된 참조를 사용하여 빠르게 메모리에 접근
- 심볼릭 참조 → 메모리 참조 변환 : 런타임에 정확한 메모리 위치를 찾을 수 있습니다.
- String Pool : 문자열 리터럴은 Runtime Constant Pool에서 관리되며 String Pool로 최적화됩니다.
정리
사실 이 위까지는 강의 및 내가 공부한대로 메모한 것이라고 보면된다.
아래에 내용정리를 해뒀다. 참고하면서 공부하면된다.
메모리 영역 비교

1.1 Heap 영역
역할
객체(instance)들이 저장되는 메모리 영역.
특징
객체와 배열이 저장됨.
Garbage Collector(가비지 컬렉터)에 의해 관리됨.
어플리케이션이 실행되는 동안 필요한 객체들이 저장됨.
역할
클래스에 대한 메타 정보(Class Metadata)가 저장되는 영역.
특징
JVM이 클래스와 관련된 메타 정보를 저장함.
클래스의 이름, 필드 정보, 메서드 정보, 접근 제어자 등이 포함됨.
클래스 로더가 클래스 파일을 읽고, 이 정보를 Meta 영역에 저장함.
Java 8부터 Meta 영역은 Native 메모리 영역으로 이동.
2.1 JVM은 클래스 정보를 기준으로 동작
클래스 메타 정보 없이는 객체를 생성할 수 없음.
JVM은 클래스의 구조(필드, 메서드, 접근 제어자 등)를 메타 데이터 영역에서 참조하여 객체를 생성합니다.
2.2 Garbage Collector (GC)의 효율성
GC는 객체를 정리하지만, 메타 데이터 영역이 없다면 GC조차 객체의 참조 여부를 판단할 수 없습니다.
GC가 객체를 어떻게 다룰지 결정하는 클래스 메타 정보가 Meta 영역에 저장됩니다.
2.3 Reflection (리플렉션) 지원
Java의 Reflection API는 클래스의 메타 데이터를 참조하여 런타임에 객체 정보를 읽고 조작할 수 있습니다.
예: 메서드 호출, 필드 접근, 어노테이션 확인 등.
2.4 JVM 최적화
JIT(Just-In-Time) 컴파일러가 코드 최적화를 수행할 때 클래스 메타 정보를 사용합니다.
메타 데이터는 JVM이 코드를 최적화하고 빠르게 실행하기 위한 중요한 데이터입니다.
2.5 클래스 로딩과 언로딩
클래스가 로딩될 때 메타 데이터 영역에 클래스 정보가 저장됩니다.
불필요한 클래스는 메타 데이터 영역에서 제거됩니다.
👉 3. 결론
- 클래스 정보 저장: 객체 생성과 실행에 필요한 모든 메타 정보가 저장됨.
- GC 효율성: 객체를 관리하고 메모리를 최적화하는 데 필요한 정보를 제공함.
- Reflection 지원: 런타임에 동적으로 클래스 정보를 조회하고 사용할 수 있음.
- JVM 최적화: JIT 컴파일러가 코드 최적화에 활용.
- 클래스 로딩/언로딩 관리: 클래스 생명주기 관리를 담당.
Heap 영역은 객체(instance)를 저장하지만, Meta 데이터 영역은 객체를 생성하고 관리하기 위한 '설계도' 역할을 한다. 따라서 Meta 영역이 JVM의 동작에 더 핵심적이다.