JVM은 자바 가상 머신(Java Virtual Machine)의 약자이다.
JVM은 자바 소스코드로부터 만들어지는 자바 바이너리 파일(. class)을 실행할 수 있다. 또한 JVM은 플랫폼에 의존적이다. 즉 리눅스의 JVM과 윈도우즈의 JVM은 다르다. 단, 컴파일된 바이너리 코드는 어떤 JVM에서도 동작시킬 수 있다.
클래스 로더 시스템 이란?
class에서 바이트코드를 읽고 메모리에 적절하게 배치하는 것이 클래스 로더 시스템가 하는 일이다.
여기서 클래스 로더 시스템이 크게 3가지로 나누어 볼 수가 있는데 로딩, 링크, 초기화 이다.
로딩(loading) : class에서 바이트코드를 읽어오는 과정이다.
링크(Linking) : 레퍼런스를 연결하는 과정이다. 링크에서도 3가지로 나눌 수가 있다.
검증 : 바이트코드 검증 기는 생성된 자바 바이트코드가 적절한지 아닌지에 대해서 검증하며 검증이 실패할 경우 검증 오류를 보낸다.
준비 : 모든 정적 변수의 메모리가 할당되며 기본 default 값으로 할당된다.
해석 : 메모리 참조를 메서드 영역에 있는 타입으로 직접 참조한다.
초기화 : static 값들 초기화 및 변수에 할당한다.
메모리
메모리는 총 5가지 영역으로 구분할 수 있다.
메서드 영역(Method Area)
모든 클래스 수준(클래스명, 부모 클래스명, 메서드, 변수)등 데이터가 저장이 된다
공유자원이며 JVM당 하나의 영역밖에 존재하지 않는다.
힙 영역(Heap Area)
모든 인스턴스 오브젝트(클래스, 배열 등) 저장되는 공간이다. JVM당 하나의 영역밖에 존재하지 않으며 또한 공유자원이다. 위의 메소드 영역에 있는 데이터와 마찬가지로 멀티스레드에서 접근이 가능한 공유자원이기 때문에 스레드에 안전하지 않다.
메서드 영역, 힙 영역은 멀티스레드에서 접근이 가능한 공유자원이었다면 나머지 스택, PC, 네이티브 메서드 스택은 스레드에 국한되어 있다.
스택 영역 (Stack Area)
각각의, 스레드마다 개별의 스택 영역이 존재한다. 메서드 콜 스택(또는 run time stack)이 메서드가 호출될 때마다 스택에 스택 프레임이라는 스택 메모리에 쌓이게 된다. 모든 지역변수가 스택 메모리에 저장될 것이다.
run time stack 이란?
함수를 실행하고 제어하는데 필요한 정보를 저장하는 공간을 차례로 보관하는 곳이다.
함수를 실행하고 제어하는 데 필요한 정보를 저장하는 공간을 차례로 보관하는 곳
PC레지스터
현재 실행 중인 명령문의 주소를 가지기 위해 각각의 스레드마다 개별 PC레지스터가 존재한다.
여기서 PC는 Program Counter의 약자이다.
Native Method Stacks
native 메서드 정보를 가지고 있는 스택, 개별 스레드마다 생성된다.
실행 엔진
실행 데이터 영역에서 할당된 바이트 코드는 실행 엔진에 의해서 실행된다. 실행 엔진은 바이트코드를 읽으며 조각단 위 별로 실행한다.
인터프리터(Interpreter)
인터프리터는 바이트코드를 빠르게 해석하지만 실행 속도는 느리다. 인터프리터의 단점은 하나의 메서드가 여러 번 호출되었을 때, 매번 새로운 해석(interpretation)이 필요하다.
JIT 컴퍼 일러(Just - In - Time)
JIT 컴파일러는 인터프리터의 단점을 보완해준다. 실행 엔진은 바이트코드를 변환하는 데에 인터프리터의 도움을 받을 테지만 코드가 발견되었을 시에는 JIT 컴파일러를 사용해서 반복되는 부분을 native code로 컴파일한다.
JIT 컴파일러 역할
1. Intermediate Code 생성기 - Intermediate Code 생성
2. 코드 최적화 - Intermediate Code를 최적화함
3. 타겟 코드 생성 - 원시 코드(native code) 생성
4. 프로파일 - 특정 메서드가 여러 번 실행했는지 안 했는지를 판별해주는 special component
GC(Garbage Collecotor)
더 이상 참조되지 않는 객체를 모아서 정리한다.
- GC에 대한 더 자세한 내용은 https://jungkeung.tistory.com/75 에서 참고하자.
JNI(Java Native Interface)
자바 애플리케이션에서 C, C++, 어셈블리로 작성된 함수를 사용할 수 있는 방법 제공
Native 키워드를 사용한 메서드 호출
네이티브 메서드 라이브러리
C, C++로 작성된 라이브러리
정리
클래스로더가 읽으면 메모리에 배치를 함 (힙, 메소드 ). 실행을 할때 스레드가 만들어지면 스택, PC, 네이티브 메소드 스택이 쓰레드에 맞게 만들어진다. 실행엔진이 byte code 를 한줄 씩 실행을 하면서 어떤 코드는 스택에 넣는것도 있고 빼내서 더하는 것도 있을것이고 이렇게 실행하면서 스택을 사용한다. 그런데 한줄씩 하는것이 비효율적이다 보니 JIT컴파일러도 쓰고, 메모리도 최적화 해주어야하니까 남는 레퍼런스 (인스턴스) 도 찾아서 정리해도 해준다. 메모리나 실행엔진이 네이티브 라이브러리를 사용한다하면 JNI (네이티브 메소드 인터페이스)를 통해 사용하도록 되어 있는 구조이다.
참고 자료
https://sas-study.tistory.com/262
https://hyokeun0419.tistory.com/77
백기선 - 더 자바, 코드를 조작하는 다양한 방법 (인프런)
'Language > Java' 카테고리의 다른 글
java8과 java11 차이점 (0) | 2022.05.08 |
---|---|
클래스 로더 시스템 (0) | 2022.05.05 |
네이버 페이 (Naver Pay) 기능구현 (0) | 2022.04.24 |
카카오 페이( Kakao pay) 기능구현 (2) | 2022.04.23 |
생성자 (0) | 2021.11.27 |