읽기 전
- 불필요한 코드나 잘못 작성된 내용에 대한 지적은 언제나 환영합니다.
- 개인적으로 사용해보면서 배운 점을 정리한 글입니다.
문제 제기
Java는 JVM이라는 가상 머신을 통해 OS 종류와는 관계 없이 구동 환경만 적합하면 코드를 실행할 수 있다. 따라서 Java의 특징적인 컴파일 환경, JVM의 구조 등을 정리하려 한다.
해당 파트는 java 소스코드 작성 후 컴파일 프로세스와 jvm에 바이트 코드 실행 시 내부 데이터를 저장 및 관리하는 흐름에 대한 내용이다.
컴파일 흐름 및 자바 가상 머신의 구성
- 개발자가 자바 소스 코드(.java)를 작성
- 자바 컴파일러(javac)가 자바 소스 코드파일 컴파일 수행
- 자바 바이트코드(.class) 파일 생성
- OS는 non-Readable, JVM은 Readable
- 바이트 코드의 명령어는 1바이트 크기의 opcode와 추가 피연산자로 구성
- 컴파일된 바이트 코드를 JVM의 클래스 로더에 전달
- 클래스 로더가 클래스 파일을 JVM 내부로 로딩, 파일을 분석하여 런테임 데이터 영역에 배치
- 동적 로딩을 수행하므로 런타임 시점이 되어야 모든 코드가 JVM과 링크됨
- 클래스 로더 세부 동작
- 로드 : 바이트 코드 파일을 가져와서 JVM 메모리에 적재
- 검증 : 자바 언어 및 JVM 명세에 명시된 대로 구성되어 있는지 검사
- 준비 : 클래스가 필요로 하는 메모리 할당 (필드, 메소드, 인터페이스 등)
- 분석 : 클래스의 Constatnt Pool 내에 저장된 모든 Symbolic Reference를 Direct Reference로 변경
- 초기화 : 클래스 변수를 적절한 값으로 초기화(static)
- 실행 엔진(Execution Engine)은 JVM 메모리에 적재된 바이트 코드들을 명령어 단위로 하나씩 가져와서 실행함, 실행 방식은 두 가지로 나뉨
- 인터프리터 : 바이트 코드 명령어를 하나씩 읽고 해석하고 실행, 명령어 실행 단위 시간은 빠르나 전체적인 실행 속도는 느림
- JIT(Just-In-Time) 컴파일러 : 인터프리터의 단점을 보완하기 위해 도입되었으며 바이트 코드 전체를 컴파일하여 기계어로 변경한 후 해당 메소드를 더 이상 인터프리팅하지 않고 바이너리 코드로 직접 실행, 전체 실행 속도는 빠르나 초기 변환 비용이 발생
- 가비지 컬렉터(Grabage Collector)
- 참조되지 않는 객체들을 탐색 후 삭제
- 삭제된 객체의 메모리 반환
- 힙 메모리 공간 확보(다른 공간의 경우도 확보할 경우 있긴 함)
'Development > Java' 카테고리의 다른 글
Java 명령어 실행 시 파일 확장자를 제거하는 이유 (0) | 2021.10.21 |
---|---|
Java float, double, BigDecimal - 부동소수점 오차 (2) | 2021.10.21 |
Java 메소드를 클래스에 넣어야 하는 이유 - .class 파일 구조 (0) | 2021.10.21 |
Java 객체와 변수 데이터의 저장 (0) | 2021.10.21 |
Java 런타임 데이터 영역 (8) | 2021.10.21 |