이 글의 개념 및 코드들은 책을 읽으며 정리한 내용을 바탕으로 작성하였습니다.
클래스 로더 시스템
-
.class에서 Byte Code를 읽고 메모리에 저장한다.
-
클래스 로더 시스템이 끝나면
해당 Class Type의 Class 객체를 생성하여
힙 영역에 저장한다.
자세한 개념은 클래스 로더(Class Loader) 글을 참고하자.
로딩
- 클래스를 읽어오는 과정이다.
링크
- 레퍼런스를 연결하는 과정이다.
초기화
- static 값들을 초기화 및 변수에 할당하는 과정이다.
메모리
Stack 영역
-
Thread 마다 런타임 Stack을 생성한다.
-
Thread가 종료되면 Stack은 초기화 된다.
-
해당 Thread안에서
이뤄지는 작업들은 Stack Frame Block 단위로 Stack에 적재한다.
PC(Program Counter) 레지스터
- Thread 내 현재 실행할 Stack Frame을 가리키는 포인터이다.
Stack 영역에는
엄청나게 많은 Stack Frame이 적재되어 있다.
그런데 외부 요인으로 인해
현재 Thread가 점유하여 사용하고 있는
CPU 자원을 Interrupte를 당하게 될 수 있다.
이 경우 현재까지 작업하고 있는
History는 Stack에 저장을 하고
나중에 다시 Thread가 CPU를 할당받았을 경우
어떤 작업부터 다시 수행해야하는지
가리키는 변수가 PC 레지스터이다.
네이티브 메소드 Stack (Native Method Stack)
-
C, C++로 구현되어있는 라이브러리를 사용하는 경우
JNI(Java Native Interface)를 통해 Native Method Library를 사용한다.
힙 영역
- 객체(=인스턴스)를 저장 및 공유한다.
메서드 영역
-
클래스 수준의 정보(클래스 이름, 부모 클래스 이름, 메소드, 변수)를 저장한다.
-
다른 Thread 사이에서 공유되는 자원이다.
Method 영역에 저장하는 데이터
-
Type 정보 (클래스, 인터페이스, Enum)
-
메소드와 변수
-
FQCN (Fully Qualified Class Name)
package goodgid.gidhub;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class GidhubApplication {
public static void main(String[] args) {
// FQCN 사용
org.springframework.boot.SpringApplication.run(GidhubApplication.class, args);
// FQCN 사용 X
SpringApplication.run(GidhubApplication.class, args);
}
}
Native Method
JNI(Java Native Interface)
-
Java 어플리케이션에서
C, C++ 등 언어로 작성된 함수를 사용할 수 있는 인터페이스를 제공한다.
-
Native 키워드를 사용한 메소드를 호출한다.
public class JVM {
// Do Something
Thread.currentThread();
}
/**
* Returns a reference to the currently executing thread object.
*
* @return the currently executing thread.
*/
public static native Thread currentThread();
Native Method Library
- C, C++ 등으로 작성 된 라이브러리이다.
실행 엔진
Interpreter
-
Byte Code를 기계가 이해할 수 있도록
Native Code로 바꾸는 작업을 한다.
-
그리고 그 동작 과정은
Byte Code 한 줄마다
컴파일을 하여
Native로 변환하는 작업을 하게 되는데
중복되는 Byte Code들에 대해서도
매번 컴파일을 하게 되면
비효율적이며 Running Time도 길어지게 된다.
-
그래서 중복되는
Byte Code에 대해서는
JIT 컴파일러를 사용한다.
JIT(Just In time) 컴파일러
-
Interpreter 효율을 높히기 위해
Interpreter가 반복되는 코드를 발견하면
JIT 컴파일러로 반복되는 코드를 모두
Native Code로 바꾼다.
-
그렇게 되면 반복된 Byte Code는
Native Code로 바뀌어 있기 때문에
Interpreter가 바로 사용할 수 있게 된다.
GC
- 더이상 참조되지 않는 객체를 정리한다.
Summary
-
JVM은 굉장히 어려운 개념이고
보다 자세히 알아야하지만
해당 포스팅에서는 Rough하게 다뤘다.
-
JVM의 큰 그림이라도 익혔으면 하는 바람으로 포스팅하였고
JVM에 대해 더 깊게 알고 싶다면 추가 학습을 하도록 하자.