JVM internal 아키텍처 에서 클래스 로더 시스템을 자세하게 그리면 위와 같이 구성되어 있다.
참고 https://hyokeun0419.tistory.com/77
클래스 로더
- 로딩, 링크, 초기화 순으로 진행된다.
- 로딩
- 클래스 로더가 .class 파일을 읽고 그 내용에 따라 적절한 바이너리 데이터를 만들고 "메소드" 영역에 저장
- 이 때 메소드 영역에 저장하는 데이터
- FQCN(fully qualified class name, 패키지 경로까지 포함된 클래스 이름) , 클래스 | 인터페이스 | 이늄, 메소드와 변수
- 로딩이 끝나면 해당 클래스 타입의 Class 객체를 생성하여 "힙" 영역에 저장
- 특정 클래스를 읽을 때 최상위 부모에게 먼저 읽어달라는 요청을 한다. (Bootstrap > Extension > Application)
- 읽지 못하였을 경우 ClassNotFoundException 이 발생하는데, 보통 의존성 추가를 제대로 하지 않고 클래스를 읽을때 볼 수 있는 에러이다.
- 링크
- 로딩이 되면 그 다음 링크 과정을 거친다.
- Verify, Prepare, Resolve(optional) 세 단계로 나눠져 있다.
- Verify : .class 파일 형식이 유효한지 체크한다.
- Preparation : 메모리를 준비하는 과정 즉, 클래스 변수 (static 변수)와 기본값에 필요한 메모리를 준비하는 과정
- Resolve : 심볼릭 메모리 레퍼런스를 메소드 영역에 있는 실제 레퍼런스로 교체한다. 이 과정은 optional 이다.
- 예를들어 Book book = new Book(); 은 실제 레퍼런스를 참조하고 있지 않고 논리적인 레퍼런스를 참조하고 있다.
이를 실제 힙에 들어있는 Book 객체 인스턴스를 가리키도록 하는 과정이 이 때 나타날 수도 있다. (Optional)
- 예를들어 Book book = new Book(); 은 실제 레퍼런스를 참조하고 있지 않고 논리적인 레퍼런스를 참조하고 있다.
- 초기화
- 링크 단계에서 Prepare 시 메모리는 준비해놨다면, 실제 이 시점에 Static 변수의 값을 할당된다.
(static 블럭이 있다면 이때 실행된다.)
- 링크 단계에서 Prepare 시 메모리는 준비해놨다면, 실제 이 시점에 Static 변수의 값을 할당된다.
- 클래스 로더는 계층 구조로 이뤄져 있으면 기본적으로 세가지 클래스 로더가 제공된다.
- 부트 스트랩 클래스 로더 - JAVA_HOME\lib에 있는 코어 자바 API를 제공한다. 최상위 우선순위를 가진 클래스 로더
- 플랫폼 클래스로더 - JAVA_HOME\lib\ext 폴더 또는 java.ext.dirs 시스템 변수에 해당하는 위치에 있는 클래스를 읽는다.
- 애플리케이션 클래스로더 - 애플리케이션 클래스패스(애플리케이션 실행할 때 주는 -classpath 옵션 또는 java.class.path 환경 변수의 값에 해당하는 위치)에서 클래스를 읽는다.
이 모든것은 바이트 코드가 있어야 돌아가므로 바이트 코드가 가장 중요하다.
컴파일이 되면 바이트코드가 생기고 그 다음에 JVM 이 위 구조를 사용해서 실행하는 것이다.
이 과정에서 중요한것은 바이트 코드인데, 이 바이트 코드를 조작 할 수도 있다. (source 파일 없이도 직접 만들 수도 있다.)
참고
백기선 - 더 자바, 코드를 조작하는 다양한 방법
'프로그래밍 > Java' 카테고리의 다른 글
Lombok 동작원리 (0) | 2022.05.03 |
---|---|
다이나믹 프록시 (0) | 2022.05.03 |
JVM 구조 (0) | 2022.04.30 |
JDK, JRE, JVM 이해하기 (0) | 2022.04.29 |
Java 8 Funtional 스터디 (0) | 2021.09.23 |