Search
Duplicate
😀

01. JVM은 무엇이며 자바 코드는 어떻게 실행하는가?

태그
JVM
Java 컴파일
JVM 아키텍처
JDK/JRE

JVM (Java Virtual Machine)

Java Virtual Machine의 약자로, Java Byte Code를 OS에 맞게 해석해주는 역할을 함
1.
자바와 OS 사이에 위치해 중간 역할을 함
Java Byte Code는 기계어가 아니기 때문에 OS에서 바로 실행할 수 없다.
이것을 OS가 해석할 수 있도록 변환하는 역할을 하는게 JVM!
Java는 JVM 덕분에 CPU나 OS(플랫폼)과 독립적으로 동작 가능하다
중간단계의 존재로 C언어같은 네이트 언어에 비해 속도가 느리다는 단점이 존재
JIT(Just In Time) 컴파일러를 통해 속도저하를 극복
2.
자바애플리케이션을 클래스 로더를 통해 로딩시켜 자바 API와 함께 실행시키는 역할을 함
3.
Garbage Collector를 통해 메모리 관리를 자동으로 해준다.

JVM 구조 및 실행과정

JVM의 3가지 서브시스템

1.
클래스 로더 시스템
2.
실행 데이터 영역
3.
실행 엔진

클래스 로더 시스템 (Class Loader)

자바 컴파일러가 .java 파일을 컴파일하면 .class 파일(바이트 코드)가 생성된다. 생성된 클래스 파일들을 엮어 Runtime Data Area 형태로 메모리에 적재하는 역할을 한다.
1.
로딩(Loading)
Bootstrap ClassLoader
jre의 lib 폴더에 있는 rt.jar 파일을 확인하여 기본 java API 라이브러리를 로드
Extension ClassLoader
jre의 lib/ext 폴더에 있는 모든 확장 코어 클래스파일들을 로드함
Application ClassLoader(System ClassLoader)
사용자가 직접 정의한 클래스파일들을 로드함
2.
연결(Linking)
검증 (verify)
바이트코드 검증기는 생성된 자바 바이트코드가 적절한지 아닌지에 대해 검증함
준비 (prepare)
모든 정적변수의 메모리가 할당되며, 기본 default 값으로 할당됨(아직 초기화는 X)
해석 (resolve)
심볼릭한(명확하게 정의되지 않은) 메모리 참조를 메서드 영역에 있는 타입으로 직접 참조함
3.
초기화(initialize)
모든 정적 변수가 자바 코드에 명시된 값으로 초기화되며, 정적 블록이 실행됨

실행 데이터 영역 (Runtime Data Area)

JVM이 변경한 .class 파일이 메모리에 로드되는 공간 모든 스레드가 공유하는 Method Area, Heap Area와 스레드마다 하나씩 생성되는 Stack, PC Register, Native Method Stack이 존재한다.
메서드 영역(Method Area)
프로그램 흐름을 구성하는 바이트 코드가 저장되는 영역
클래스 멤버 변수, Method 정보, Type(Class or Interface) 정보, Constant Pool, static, final 변수 등이 생성되는 공간.
공유자원이며, JVM당 하나만 존재
힙 영역(Heap Area)
동적으로 생성된 오브젝트 및 배열이 저장되는 곳으로 Garbage Collection의 대상이 되는 영역
공유자원이며, JVM당 하나만 존재
힙 영역의 세부 구조
Permanent Generation - 생성된 객체 정보의 주소가 저장된 공간
Young Generation
eden - 객체들이 최초로 생성되는 공간
Survivor space - eden 영역에서 참조되는 객체들이 저장되는 공간
Old Generation - Young에서 일정 시간 이상 참조되고 있는 객체들이 저장되는 공간
스택 영역(Stack Area)
지역 변수, 메서드의 매개변수, 임시적으로 사용되는 변수, 메서드의 정보가 저장되는 영역
동적으로 객체를 생성하면 실제 객체는 Heap에 할당되고, 해당 레퍼런스만 Stack에 저장된다.
Person p = new Person(); p -> 스택 영역에 저장 new Person() -> 힙 영역에 저장
Java
복사
PC 레지스터
스레드가 시작될 때 생성되며, 현재 수행중인 JVM 명령어의 주소를 저장하는 공간
cpu 레지스터의 Program Counter X!!(다음에 시작될 명령어의 주소를 저장하는 공간이 아님)
Native Method Stack
자바 프로그램이 컴파일되어 생성되는 바이트코드가 아닌, 실제 실행할 수 있는 기계어로 작성된 프로그램을 실행시키는 영역
JNI(Java Native Interface)를 통해 호출하는 C/C++ 등 Java가 아닌 다른 언어의 코드를 수행하기 위한 공간

실행 엔진 (Runtime Engine)

실행 데이터 영역에서 할당된 바이트 코드는 실행엔진에 의해서 실행됨 실행엔진은 바이트 코드를 읽으며 조각 단위별로 실행
인터프리터
인터프리터는 바이트코드를 빠르게 해석하지만 실행속도는 느리다
하나의 메서드가 여러번 호출되었을 때, 매번 새로운 해석이 필요하기 때문에
JIT 컴파일러(Just-In-Time)
JIT 컴파일러는 인터프리터의 단점을 보완해준다.
실행엔진은 기본적으로 바이트코드를 변환하는데 인터프리터의 도움을 받지만, 반복되는 코드가 발견되면 JIT 컴파일러를 사용해서 반복되는 부분을 native code(원시 코드)로 컴파일한다
변환된 원시코드는 변환과정 없이 직접적으로 사용하며, 이로 인해 시스템 성능이 좋아진다.
가비지 컬렉터(Garbage Collector)
아무 참조가 없는 인스턴스들을 모아서 제거하는 역할을 함
** GC의 수행 과정
1.
Young Generation부터 수행된다.
a.
eden 영역이 가득차게 되면 첫 번째 GC가 수행되고 S0 영역으로 옮긴다.
b.
이후에 eden 영역과 S0 영역의 메모리가 기준치 이상인 경우에는 eden과 S0의 데이터 중 참조하고 있는 메모리를 S1으로 옮기고 나머지는 제거한다.
c.
S1이 가득 차면 S0로 옮기고 왔다갔다 반복한다.
2.
일정 시간이 지났을 때 계속 참조되고 있는 메모리를 Old Generation으로 복사하고, 위의 과정을 반복한다.

Java 실행 과정

1.
프로그램이 실행될 때 OS로부터 메모리를 할당받는다.
2.
자바컴파일러(javac)가 작성된 자바소스코드를 바이트코드(java.class)로 변환한다.
3.
바이트 코드 (클래스 파일)들을 클래스로더가 JVM 메모리 영역(Runtime Data Area)으로 로딩한다
4.
Runtime Data Area에 로딩된 클래스파일이 Excution Engine을 통해 해석된다.
5.
해석된 바이트코드들이 Runtime Data Area에 배치되어 실질적으로 수행된다.

JDK & JRE

JDK
(Java Development Kit, 자바 개발 도구)
JDK는 JRE + 개발을 위해 필요한 도구(javac, java등)들을 포함한다.
JRE
(Java Runtime Environment, 자바 실행 환경)
미리 만들어진 라이브러리를 묶어놓은 환경 (API)
JRE는 JVM 이 자바 프로그램을 동작시킬 때 필요한 라이브러리 파일들과 기타 파일들을 가지고 있다.
JRE는 JVM의 실행환경을 구현했다고 할 수 있다.