Java/The Java
[The Java] 클래스 로더와 JVM
메성
2021. 1. 3. 21:59
반응형
Java 프로그램의 실행 과정
- Java 프로그램을 실행하면 JVM은 OS로 부터 메모리를 할당받는다.
- 작성한 .java 파일은 컴파일러에 의해 .class(바이트 코드) 파일로 변환된다.
- 클래스 로더에 의해서 .class(바이트 코드가 포함된) 파일을 찾아 JVM에 올려놓는다.(런타임)
- 실행엔진에 의해 .class(바이트 코드가 포함된) 파일을 한줄 씩 실행하게 된다.
클래스 로더
- 클래스 로더는 위 그림처럼 로딩 - 링크 - 초기화 순으로 진행된다.
- 로딩
- Bootstrap(최상위 부모) <- Extension(Platform) <- Application의 클래스 로더들이 부모 자식 관계를 맺고 있다.
- 클래스 로더의 동작 : 클래스를 읽을 때, 최상위 부모에서부터 읽을 수 있는지 확인 후 못 읽으면 자식 클래스 로더로 내려온다. 만약 Application 클래스 로더도 못 읽게 되면 ClassNotFoundException이 발생하게 된다.
- BootStrap : JVM이 실행될 때 실행되는 클래스 로더로서 $JAVA_HOME/lib/ext/*.jar에 있는 가장 기본이 되는 라이브러리들을 로드한다.
- Extension : $JAVA_HOME/lib/ext/*.jar에 있는 클래스들을 로드한다.
- Application(System) : 사용자가 지정한 $CLASSPATH 내의 클래스들을 로드한다.
- User-Defined(사용자 정의) : 사용자가 직접 코드 상에서 생성한 클래스들을 로드한다.
- 전체적으로 클래스 로더가 .class 파일을 읽어 적절한 바이너리 데이터를 만들고 JVM의 메소드 영역에 저장한다.
- 이 때 메소드 영역에 저장되는 데이터 : FQCN(패키지 이름, 풀 패키지 경로, 클래스 이름), 클래스, 인터페이스, Enum, 메소드와 변수
- 이로 인해 java.lang.reflect 활용하여 로딩된 클래스들의 정보를 확인할 수 있다.
- 로딩이 끝나면 해당 클래스 타입의 Class 객체를 생성하여 힙 영역에 저장한다.
- Bootstrap(최상위 부모) <- Extension(Platform) <- Application의 클래스 로더들이 부모 자식 관계를 맺고 있다.
- 링크
- Verify : 로드된 .class 파일의 형식이 유효한지 체크한다.
- Preparation : 클래스 및 인터페이스의 static 필드를 생성하고 기본값으로 초기화한다.
- Resolve : 심볼릭(명확하게 정의되지 않은)하게 참조한 메모리 부분을 인스턴스들의 실제 주소값으로 참조하게 한다.
- 초기화
- 링크 단계에서 기본값으로 초기화된 static 필드들에 대해 정의된 값으로 지정해준다.
JVM
-
클래스 로더 시스템
- .class에서 바이트 코드를 읽고 JVM의 메소드 영역에 저장한다.
- 로딩 : 클래스를 읽어온다.
- 링크 : 실제 주소값 참조
- 초기화 : static 값들을 메모리에 할당한다.
-
메모리
- 메소드 영역에는 클래스 수준의 정보(클래스 이름, 부모 클래스 이름, 메소드, 변수)를 저장하고 공유한다. 전역변수도 포함되며 JVM에서 오직 한 영역만 존재하고 공유할 수 있어 다른 스레드에서도 접근이 가능하다.
- 힙 영역에는 객체를 저장하는 것으로, JVM에서 오직 한 영역만 존재하고 공유할 수 있으며 이 영역 또한 다른 스레드에서 접근이 가능하다.
- Class 객체의 인스턴스들도 저장된다.
- 스택 영역에는 스레드마다 런타임 스택을 만들고, 그 안에서 메소드 호출을 스택 프레임이라 부르는 블럭으로 쌓는다. 또한,스레드마다 하나씩 갖고 있는다.
- 소스에서 만든 메소드가 호출(스택 프레임)되면 스택 영역에 올라간다, 메소드 호출 범위가 종료되면 스택 영역에서 사라지게 된다.
- 메소드의 매개변수, 지역변수, 리턴 값, 연산 시 결과 값들을 임시로 저장한다.
- Ex. 오류가 발생했을 때 나오는 메소드 리스트들이 런타임 스택이다.
- PC(Program Counter) 레지스터는 스레드마다 하나씩 갖고 있으며, 현재 실행되고 있는 스택 프레임을 가리키는 포인터가 생성된다.
- 네이티브 메소드 스택은 자바로 작성되지 않고 C, C++로 작성된 메소드 스택이다. (기계어를 실행시키는 영역)
-
네이티브 메소드 인터페이스(JNI)
- Java가 아닌 C, C++로 작성된 메소드를 가진 인터페이스로서, Native 키워드를 사용하여 메소드를 호출한다.
- 네이티브 메소드 인터페이스가 존재해야지만 네이비스 메소드 스택에 리스트가 존재한다.
-
네이티브 메소드 라이브러리
- 네이티브 메소드 인터페이스의 구현체이다.
-
실행엔진
- 인터프리터는 바이트 코드를 한줄씩 컴파일하여 네이티브 코드(컴퓨터가 읽을 수 있는 코드)로 변환하고 실행한다.
- JIT 컴파일러는 인터프리터 방식의 단점을 보완하는 것이다.
- 인터프리터는 한줄씩 실행하기 전에 반복되는 코드를 전부 찾아 JIT 컴파일러로 보내고, JIT 컴파일러는 받은 바이트 코드를 네이티브 코드로 변경해놓는다.
- 그 후 인터프리터는 다시 실행하여 네이티브 코드면 그냥 사용하고, 그렇지 않은 것만 컴파일하는 것으로서, 좀 더 빠르게 되는 것이다.
-
GC
- 힙 영역에 있는 New/Young Generation과 Old Genaration 영역에 있는 객체들을 정리한다.
- New/Young Generation은 Minor GC가 발생하고 Old Generation은 Major GC가 발생한다.
https://it-mesung.tistory.com/56
GC에 대해서 더 살펴보자
https://it-mesung.tistory.com/58
반응형