자바는 썬 마이크로시스템즈의 제임스 고슬링과 다른 연구원들이 개발한 객체 지향적 프로그래밍 언어 이다
JRE + JDK + API
JDK (Java Development Kit) : Java 개발을 위한 툴킷. JRE + 개발 도구 포함
JRE (Java Runtime Environment) : Java 애플리케이션 실행 환경. JVM + 핵심 라이브러리 포함
JVM (Java Virtual Machine) : 바이트코드를 실행하는 가상 머신
API (Application Programming Interface) : 표준 라이브러리(Java SE, EE, ME)와 외부 라이브러리 포함
Development Tools : Java 컴파일러(javac), 디버거(jdb) 등 개발에 필요한 도구들
출처 : https://wonsjung.tistory.com/574java 프로그램이 실행되는 가상 컴퓨터
한 번 작성하면 어디서든 실행 가능 (Write once, run anywhere)
OS는 JVM에게 메모리 할당 권한을 부여한다
*.java 파일 모두 javac 로 컴파일 → *.class 로 변환 (여기는 JVM 아님)
실행에 필요한 클래스만 클래스로더가 로딩해서 Runtime Data Area 에 적재 (Lazy Loading)
로딩 시점
로딩된 클래스는 해당 클래스와 그 클래스에 대한 모든 참조가 GC 대상이 될 때만 메모리에서 해제(unload)
클래스 로딩 후, 코드 실행 시에 메모리 할당이 필요한 경우 Runtime Data Area 의 적당한 영역에 메모리 할당
메모리 할당 이후, Interpreter 가 바이트코드를 기계어로 변환. 자주 변환되는 메서드일 경우(HotSpot), JIT 컴파일러가 개입하여 캐싱
위 2 ~ 4 가 메서드 단위로 반복되면서 계속 실행
Java 는 모든 코드가 메서드 안에서 실행되므로 메서드 단위로 반복
*.class 파일을 Runtime Data Area에 적재하는 역할을 한다. 런타임에 클래스를 처음 참조할 때 이 작업이 수행된다
Loading : 클래스 로드
| ClassLoader | 역할 | 우선순위 |
|---|---|---|
| BootStrap ClassLoader | Java의 최상위 클래스 로더. java.lang 패키지 등 기본 클래스를 로드 | 가장 높음 |
| Extension ClassLoader | lib/ext/ 디렉토리의 확장 클래스를 로드 | 중간 |
| Application ClassLoader | classpath에 있는 애플리케이션 클래스를 로드. 응용 프로그램 수준 클래스 경로, 환경 변수 등을 로드. 클래스 파일을 로드하는 동안 위임 계층 알고리즘을 따름 | 가장 낮음 |
Linking : JVM이 클래스를 실행하기 전에 클래스의 바이트코드를 준비하는 과정. 이 과정에서 클래스의 정적 정보(Static Information)를 검증하고 메모리에 할당한 후 참조를 해결한다
| 단계 | 설명 |
|---|---|
| Verify (검증) | 바이트코드가 유효한지 확인. 보안 및 안정성을 위해 검증 수행 |
| Prepare (준비) | 클래스의 정적 변수(static field)를 메모리에 할당하고 기본값 설정 |
| Resolve (해결) | 심볼릭 참조를 실제 메모리 주소로 변환 (필요할 때 수행됨) |
Initialization : static 변수와 static 블록을 실행. 모든 static 변수는 원래 값으로 지정된다
출처 : https://technote-mezza.tistory.com/72
Method Area : 모든 클래스 레벨의 데이터가 static 변수를 포함하여 여기에 저장됨. JVM 당 단 하나의 메서드 영역이 있으며 공유 자원이다
클래스 레벨의 데이터
Heap Area : 모든 객체와 해당 인스턴스 변수 및 배열이 여기에 저장된다. 공유 자원이다.
new 키워드로 생성된 객체와 배열이 생성되는 영역으로 메서드 영역에 로드된 클래스만 생성이 가능하고 Garbage Collector가 참조되지 않는 메모리를 확인하고 제거하는 영역이다.
Stack Area : 지역 변수, 파라미터, 리턴 값, 연산에 사용되는 임시 값 등이 생성되는 영역으로서 메서드를 호출할 때마다 개별적으로 스택이 생성된다. 이 영역 안에서도 Local Variable Array, Operand stack, Frame data로 나뉘게 된다. 스택 영역은 공유 자원이 아니므로 스레드 안전 영역이다
PC register : 스레드가 생성될 때마다 생성되는 영역으로 Program Counter 즉, 현재 스레드가 실행되는 부분의 주소와 명령을 저장하고 있는 영역이다. (*CPU의 레지스터와 다름) 이것을 이용해서 스레드를 돌아가면서 수행할 수 있게 한다. 공유 자원이 아니다
Native Method Stack : 자바 외 언어로 작성된 네이티브 코드를 위한 메모리 영역이다. 보통 C/C++ 등의 코드를 수행하기 위한 스택이다. 공유 자원이 아니다
JNI(Java Native Interface) : Native Method Libraries와 상호 작용하고 Execution Engine에 필요한 Native Libraries를 제공
ClassLoader로부터 받은 runtime data area에 있는 *.class파일(바이트코드)을 기계어로 변환시키는 역할을 한다. 바이트 코드를 읽어 조각 별로 실행한다. interpreter와 JIT 방식이 있다
| 방식 | 설명 | 장점 | 단점 |
|---|---|---|---|
| Interpreter (인터프리터) | 바이트코드를 한 줄씩 해석하여 실행 | 빠른 실행 시작 | 실행 속도가 느림 (반복 코드 비효율적) |
| JIT (Just-In-Time) Compiler | 바이트코드를 한 번에 네이티브 코드로 변환 후 실행 | 실행 속도 빠름 (최적화 적용) | 초기 변환 시간이 필요 |
* 네이티브 코드(Native Code)는 여러 개의 CPU 명령어(Instructions)로 구성된 코드 블록이다
Heap 메모리 영역에 생성(적재)된 객체들 중에 참조되지 않은 객체들을 탐색 후 제거하는 역할을 한다.
GC가 역할을 하는 시간은 정확히 언제인지를 알 수 없다. (참조가 없어지자마자 해제되는 것을 보장하지 않는다는 의미) "System.gc ()"를 통해 GC를 호출할 수 있지만 실행이 보장되지는 않는다.
또 다른 특징은 GC가 수행되는 동안 GC를 수행하는 스레드가 아닌 다른 모든 쓰레드가 일시 정지된다. 특히 Full GC가 일어나서 수 초간 모든 스레드가 정지한다면 장애로 이어지는 치명적인 문제가 생길 수 있는 것이다.