JVM에 대한 정의는 해당 포스트를 참고해주세요.
JVM이 동작하는 순서는 다음과 같다. (구성요소 - class loader, runtime data area, execute engine, JNI...)
- 자바 프로그램을 실행하면 JVM은 OS로부터 메모리를 할당한다.
- 자바 컴파일러(javac)가 자바 소스코드(.java)를 자바 바이트코드(.class)로 컴파일한다.
- Class Loader를 통해 JVM Runtime Data Area로 로딩한다.
- Runtime Data Area에 로딩 된 .class들은 Execution Engine의 인터프리터와 JIT 컴파일러를 통해 해석합니다.
- 해석된 바이트 코드는 Runtime Data Area의 각 영역에 배치되어 수행하며 이 과정에서 Execution Engine에 의해 GC가 작동하고, 스레드 동기화가 이루어진다.
- Class loader 시스템: 바이트를 실행할 때 class 객체를 메모리에 생성하는 요소.
클래스의 인스턴스를 생성하면 클래스로더를 통해서 메모리에 로드한다.
기본적으로 클래스로더 기능은 3가지가 제공된다. - 로딩, 링크, 초기화 기능.- 로딩: .class파일에서 읽고 그 내용에 따라 바이너리 데이터를 이를 메소드영역에 저장한다.
로딩이 끝나면 해당 클래스 타입의 class객체를 생성해서 힙 영역에 저장한다.
해당 클래스 정보를 FQCN이라고 한다. (fully qualified class name.) 클래스, 인터페이스, enum, 메서드, 변수를 저장함- 부트스트랩 클래스로더: JAVA_HOME\lib 에 있는 코어 자바 API를 제공한다. 최상위 우선순위를 가짐
- 플랫폼 클래스로더: JAVA_HOME\lib\ext 폴더 혹은 java.ext.dirs 시스템 변수에 해당하는 위치에 있는 클래스를 읽는다.
- 어플리케이션 클래스로더: 어플리케이션 클래스패스(어플리케이션 실행할 때 주는 -classpath 옵션 혹은 java.class.path 환경 변수의 값에 해당되는 위치)에서 클래스를 읽는다.
- 어떤 클래스를 읽어올 때 최상위 부모(부트스트랩)부터 읽기 시작해서 모든 클래스로더가 읽지 못하면 ClassNotFoundException이 발생한다. 대부분 application 클래스로더가 읽게 된다. (스프링 등..)
- 링크: 레퍼런스를 연결
- verify: .class파일 형식이 유효한지 체크
- prepare: 클래스변수(static)와 기본값에 필요한 메모리를 준비하는 과정.
- resolve: 심볼릭 메모리 레퍼런스()를 메소드 영역에 있는 실제 레퍼런스와 교체한다. (optional: )
- 초기화: static 값들을 초기화하고 변수에 할당함
- 로딩: .class파일에서 읽고 그 내용에 따라 바이너리 데이터를 이를 메소드영역에 저장한다.
- Runtime data area(메모리): OS에서 JVM이 실행될 때 할당되어 있는 메모리영역이고, 모든 쓰레드의 공유공간이다.
- method area(class area): 클래스 수준의 정보를 저장함(Type info, Runtime Constant pool, Field info, method info, class variables)
- type info: 해당 클래스, 하위 클래스들 이름, 해당 클래스의 클래스-인터페이스 여부, 클래스의 modifier(접근제어자, abstract 등), 연관된 인터페이스 리스트
- runtime constant pool: 해당 클래스에 들어있는 모든 상수정보(type, field, method의 모든 Symbolic ref), constant pool의 entry는 인덱스로 접근
- Field info: 들어있는 필드값들에 대한 정보(type, modifier - 접근 제어자나 static, final, volatile, transient 같은 그 외 제어자들)
- method info: 메서드 이름, 리턴타입, 파라미터 수와 타입, modifier(접근제어자나 static, final, syncronized, native, abstract), 구현로직, 바이트코드, 메서드의 stack frame operand stack, local variable section 크기, exception table
- class variable: static 변수(클래스변수는 클래스에 속하게 됨. 클래스를 사용하기 이전에 이미 메모리를 할당받음)
- static 변수는 메서드 영역에 저장됨. 기본형이 아닌 static 클래스변수는 변수의 주소를 저장하고, 실제 인스턴스는 힙메모리에 저장된다.
- final static으로 선언된 클래스 상수변수는 runtime constant pool에 값을 복사한다.
- heap area: 객체들의 인스턴스가 생성되는 공간. 동적으로 인스턴스가 생성되면 Heap 메모리에 할당되어 사용된다. (Object 타입의 데이터 String, List...)
- 레퍼런스타입 변수, 배열 등은 heap에 인스턴스가 저장되는 게 아니라 포인터가 저장된다.
- GC의 대상이 되는 영역이다.
- 7버전 이후부터는 내부에 String constant pool을 포함하고 리터럴로 초기화된 String 객체들을 효율적으로 관리함
- 특정 스레드에 국한된 공간
- PC register: 쓰레드마다 쓰레드 내의 현재 실행할 instruction의 위치를 가리키는 포인터가 생성된다.
- stack area(JVM Stack): 쓰레드마다 런타임 스택을 만들고, 그 안에 메소드 호출을 스택프레임(메소드 콜)에 쌓는다. 이후 쓰레드가 종료되면 런타임 스택은 사라진다.
- native method stack: 네이티브 메소드 사용 시 따로 쓰는 스택.
- method area(class area): 클래스 수준의 정보를 저장함(Type info, Runtime Constant pool, Field info, method info, class variables)
- Execution engine(실행 엔진) - 인터프리터, JIT 컴파일러, GC
- 인터프리터, JIT 컴파일러
- 바이트코드를 인터프리터를 통해서 한 줄씩 컴파일 - 실행하면서 네이티브 코드로 바꿔서 실행한다.
- 이 중 반복적인 코드가 발생하는 부분은 JIT컴파일러가 미리 캐싱해놨던 네이티브 코드(기계어)로 변환시켜서 속도를 향상시킨다.
- GC - 메모리의 stack 영역 데이터, method 영역의 static 데이터, JNI에 의해 생성된 객체에 대하여 동작함
- 객체가 참조되는 동안 JVM은 힙 메모리의 객체가 살아있는 것으로 간주하지만, 이후에 더 이상 참조하지 않으면 GC가 객체를 제거하고 메모리 해제를 한다. GC는 JVM 내부적으로 알아서 실행되지만, System.gc() 메서드로 트리거할 수도 있다. 실행이 보장되지 않을 수 있다. 정말 필요한 경우에는Thread.sleep(1000)을 호출하고 GC가 완료될 때까지 기다린다.
- 기본적으로 Mark&Sweep 알고리즘으로 동작함. 어떤 객체에 유효한 참조가 있는지 체크 후(Reachability) unreachable한 객체들을 메모리 해제한다
- 추가로 메모리 단편화를 막기 위해 compact과정을 거치기도 함
- 경우에 따라 옵션을 조정하여 커스터마이징한다. 어플리케이션 프로파일링 시에도 우리가 어떤 GC를 사용하는지, 경우에 따라 어떤 GC를 사용해야될지 선택해야한다.
- throughput의 최대화를 위한 GC(처리용량), stop-the-world를 줄이는 GC(반응시간)
- Serial GC(JDK 5,6), Parallel GC(JDK 8 default), CMS(Concurrent Mark Sweep) collector, G1 GC(자바 7부터 도입, 9부터 default)
- 인터프리터, JIT 컴파일러
- Native
- JNI: 자바 어플리케이션에서 c, c++, 어셈블리 등으로 작성된 함수를 사용할 수 있는 방법을 제공함. native 키워드를 사용해서 메소드를 호출한다.
- 네이티브 메소드 라이브러리: c,c++로 작성된 라이브러리
- 백기선님의 자바 온라인 스터디 https://github.com/whiteship/live-study 주제를 정리한 내용입니다.
참고내용:
'Java > basic' 카테고리의 다른 글
자바 변수의 종류, 특징 - Primitive type, Reference type (0) | 2022.10.30 |
---|---|
JIT 컴파일러 동작과정 (0) | 2022.10.30 |
JVM 이란? (0) | 2022.10.30 |
String constant pool를 이해하면 왜 String이 불변으로 설계됬는지 이해할 수 있다 (0) | 2022.04.13 |
JDK, JRE의 차이 (0) | 2022.04.07 |