728x90
JVM의 정의
- 자바 가상 머신(영어: Java Virtual Machine, JVM)은 자바 바이트코드를 실행할 수 있는 주체이다.
- (가상 머신 : 물리적 컴퓨터와 동일한 기능을 제공하는 소프트웨어적으로 구현한 컴퓨터 )
- 특징
- Java와 OS사이에서 중개자 역할을 하며, OS에 구애받지 않고 재사용 가능하게 해준다.
- 그리고 가장 중요한 GC(사용하고 남아 있는 전혀 필요없는 객체들을 정리)를 수행한다.
JVM의 구조
- Runtime Data Area
- JVM이 OS위에서 실행되면서 할당받은 메모리 영역.
- 구성요소
- Stack : 스택 프레임이라는 구조체를 저장하는 스택. 스레드들이 독립적으로 갖고 있는 공간.
- Stack Frame : JVM내에서 {} 중괄호가 지삭될 때 마다 하나의 스택 프레임이 생성되고, 중괄호가 닫히면 스택 프레임이 제거된다. 현재 실행중인 메서드가 속한 클래스의 런타임 상수 풀에 대한 참조를 갖는다.
- Heap : 인스턴스 정보가 담기는 공간. 스레드들이 공유함.
- 구성 요소
- Young Generation
- Eden : 객체들이 최초로 생성되는 공간
- Survivor 0 : Eden영역에서 마이너 GC가 발생하고 이곳으로 이동한다.
- Survivor 1 : 0에서 가득차게 되면, 이곳으로 이동하게 된다. 그리고 0은 아무 데이터도 없는 상태가 된다. 이 과정을 반복하다가 계속해서 살아남아 있는 객체는 Old 영역으로 이동하게 된다. 0,1중 하나는 반드시 비어있는 상태가 된다.
- Old Generation : Young영역에서 살아남은 객체들이 저장되는 곳.
- Permanent Generation : 생성된 객체들의 주소값이 저장된 공간.
- GC : 지역변수, 정적변수, 실행중인 스레드, JNI에서 참조되지 않는 객체들은 Unreachable하여 GC의 대상이 된다.
- Young Generation
- 대부분 객체는 금방 소멸된고 Young에서 Old로의 참조가 적어서 위와같이 메모리 공간이 나뉘었다.
- 구성 요소
- Static : 클래스 정보가 담기는 공간. 스레드들이 공유함.
- 구성요소
- 런타임 상수풀 (클래스와 인터페이스 상수, 메서드와 필드에 대한 모든 메모리 주소를 담고 있는 테이블)
- 어떤 메서드나 멤버변수를 참조할 때 JVM은 런타임 상수 풀을 통해 해당 메서드나 멤버변수 실제 메모리 주소를 참조한다.
- 필드 정보
- 멤버변수의 이름, 타입, 접근제어자
- 메소드 정보
- 메소드의 이름, 리턴타입, 매개변수, 접근제어자
- 타입정보
- 클래스인지 인터페이스인지, 리턴타입, 부모 클래스 등
- 런타임 상수풀 (클래스와 인터페이스 상수, 메서드와 필드에 대한 모든 메모리 주소를 담고 있는 테이블)
- 메모리 공간에 올릴 때 초기화 되는 대상을 저장하기 위한 메모리 공간.
- 구성요소
- PC Register : 스레드가 어떤 부분을 어떤 명령으로 실행할 지에 대한 기록하는 부분. 현재 수행중인 주소와 명령을 저장함. 스레드들이 독립적으로 갖고 있는 공간.
- Native Method Stack : 스레드들이 독립적으로 갖고 있는 공간. Java Native Interface가 저장되는 공간
- Stack : 스택 프레임이라는 구조체를 저장하는 스택. 스레드들이 독립적으로 갖고 있는 공간.
- Class Loader
- 컴파일된 자바 바이트코드를 Runtime Data Area 영역으로 로드한다.
- 런타임에 클래스를 처음으로 참조할 때 클래스를 로드함.
- 종류
- 부트스트랩 클래스로더 : 최상위 클래스로더, Object 클래스를 비롯하여 Java API들을 로드함
- 익스텐션 클래스로더 : 확장 클래스들을 로드함
- 시스템 클래스로더 : 어플리케이션의 클래스들을 로드함
- 사용자 정의 클래스로더 : 사용자가 직접 코드상에서 생성하여 사용함
- 특징
- 계층구조 : 클래스로더끼리 부모-자식 관계를 이뤄 계층 구조로 생성된다.
- 위임모델 : 클래스로딩 요청은 부모 로더들로 거슬러 올라가서 부트스트랩 로더에 다다른 후 클래스를 못찾으면 그 밑으로 로딩 요청을 수행.
- 가시성제한 : 하위 클래스를 상위 로더를 찾을 수 있지만, 그 반대는 안됨.
- 언로드 불가 : 클래스를 로드할 수 있지만 거꾸로는 불가능함.
- 클래스 로드 과정(Loading,Linking,Initalization)
- Loading : 클래스파일을 가져와서 JVM의 Runtime Data Area의 스태틱 영역에 탑재한다.
- Vertification : 클래스 로드 전 JVM 명세대로 구성되어 있는지 검사한다.
- Preparation : 클래스가 필요로 하는 메모리를 할당하고 디폴트 값으로 초기화 됨. (클래스 멤버변수, 메서드, 인터페이스 등)
- Resolution : 클래스 상수 풀 내의 모든 심볼릭 레퍼런스를 다이렉트 레퍼런스로 변경 (참조하는 대상의 이름만 지칭하는 것 대신에 실제로 존재하는 물리적인 주소로 대체함)
- Initialzation : 클래스 로딩의 마지막 단계, 모든 클래스 변수들을 초기화함.
- *Linking : 메모리를 할당하고 클래스 상수 풀 내의 모든 레퍼런스를 할당된 메모리로 연결하는 과정(Vertification, Prepareation, Resolution)
- Execution Engine
- JVM내의 런타임 데이터 영역에서 배치된 바이트 코드를 실행하는 역할
- 1바이트 코드의 Operation code와 추가 피연산자로 이뤄짐.
- Interpreter : JVM에서 기본적으로 실행되는 방식. 바이트코드 명령어를 하나씩 읽어서 해석하고 실행함. 하나하나의 해석은 빠르지만 전체적인 실행속도는 느림.
- JIT (Just-In-Time)
- 인터프리터 방식의 단점을 보완하기 위해 도입됨. 인터프리터 방식으로 실행하다가, 적절한 시점에 바이트 코드 전체를 컴파일 하여 네이티브로 변경하고, 더 이상 인터프리팅 않고 네이티브 코드로 직접 실행하는 방식.
- 내부적으로 프로파일링을 통해 가장 컴파일리 필요한 핫스팟을 찾아 캐싱하고 자주 사용되지 않으면 다시 인터프리터 모드로 동작함.
JVM의 실행 순서
- JVM은 OS로부터 어플리케이션에 필요로 하는 메모리를 할당받는다.
- 자바 소스(.java)인 파일을 자바 컴파일러를 통해 자바 바이트코드로 컴파일(컴퓨터가 이해할 수 있는 언어로 번역해주는 과정) 한다.
- 컴파일된 바이트코드를 JVM의 클래스로더에게 전달한다.
- 클래스로더는 동적로딩을 통해 필요한 클래스들을 로딩 및 링크하여 런타임 데이터 영역, JVM의 메모리에 올린다.
- Loading 로드 : 클래스 파일을 가져와서 JVM의 메모리에 로드한다. (스태틱 영역에 탑재)
- 로드된 클래스를 비롯한 그의 부모 클래스의 정보.
- Class 파일이 Class, Interface, Enum와 관련 여부.
- 변수나 메소드 정보
- Vertification 검증 : 클래스 로드 전 과정중에 가장 복잡하고, 시간이 오래걸린다. JVM 명세에 명시된대로 구성되어 있는지 검사한다.
- Preparation 준비 : 클래스가 필요로 하는 메모리를 할당한다. 여기서 필요한 메모리는 멤버변수, 메서드, 인터페이스들을 나타내는 데이터의 구조 등등을 말함.
- Resoultion 분석 : 클래스 상수 풀 내 모든 심볼릭 레퍼런스를 다이렉트 레퍼런스로 변경
- Initialzation 초기화 : 클래스 변수들을 초기화 한다.
- 로딩된 클래스 파일(바이트코드)들은 Execution Engine을 통해 명령어 단위로 해석된다.
- 이 과정에서 Thread Synchonzation과 GC관리 작업을 수행한다.
'개발 > Spring' 카테고리의 다른 글
가비지 컬렉터 (0) | 2021.03.01 |
---|---|
java.lang 패키지 (0) | 2021.02.28 |
Hot Spot JVM이란? (0) | 2021.02.27 |
JIT란? (0) | 2021.02.27 |
자바(JDK)의 버전별 차이 JDK 1.4 (0) | 2021.02.27 |