JVM은 꼭 알아야 합니다...

ISAAC·2020년 12월 26일
5
post-thumbnail

※ 이 시리즈의 내용은 매우 기본적이거나 쉬울 수도 있기 때문에 놀라실 수도 있습니다. 개발자들의 주의를 요합니다.


경험있고 능력있는 개발자라면 코드를 짤 때 어플리케이션의 성능과 안정성 등을 고려할 것이지만,
부끄럽게도 나는 어플리케이션의 성능과 안정성보다는 로직의 구현 자체에 신경을 쓰는 수준이라는 생각이 드는 경향이 있다고 느껴지는 편이라고 여겨진다...ㅠㅠ(인정하고 싶어하지 않는 몸부림ㅠㅠㅠㅠ)

코드를 실행하고 내 눈앞에 결과가 나타나기까지의 과정의 중심에는 JVM이 있다. JVM을 빼놓고는 JAVA를 말할 수 없으니 꼭 이 기회에 짚고 넘어가 보자..!!




JVM은 무슨 일을 하나?

  • 실행될 클래스 파일을 메모리에 로드 후 초기화 작업 수행
  • 메소드와 클래스변수들을 해당 메모리 영역애 배치
  • 클래스로드가 끝난 후 JVM은 main 메소드를 찾아 지역변수, 객체변수, 참조변수를 스택에 쌓음
  • 다음 라인을 진행하면서 상황에 맞는 작업 수행(함수 호출, 객체 할당 등)

JVM은 운영체제로부터 독립적이다.

어떻게?

일단 우리가 운영체제에서 Java를 사용하려면 JDK를 설치해야 한다.
여기서 이 JDK는 운영체제별 종류가 다르다.
JDK안에는 JRE, API, JVM이 포함되어 있다.
즉, 운영체제마다 다른 JVM이 제공되기 때문에 독립적일 수 있다. (굳이 말하자면 JDK에 종속적이라고 할 수 있겠다.)

JVM 실행 절차

JVM은 byteCode 파일을 기계어 코드로 변환하여 실행하는 역할을 한다.

  1. Java로 작성한 코드(.java)가 컴파일
  2. 바이트코드(.class)파일로 만들어짐
  3. 이 파일은 JVM을 거쳐서 기계어 코드파일로 변환된다.

아래 이미지를 보자.

주황색 영역부터 JVM의 영역이다.
Class Library와 Java Byte Code가 JVM에게 전달되는데,
JVM 내부적으로 Class Loader라는 녀석이 이것을 전달받는다.

1. Class Loader

클래스로더는 실행에 필요한 모든 실행파일을(.class) 찾는다.

클래스로더는 아래와 같은 계층구조를 갖는다.

(Java8기준이며, Java 9부터는 … 3가지 기본클래스로더와 원칙은 유효하나 모듈시스템도입에 따라 구현내용이 바뀌었다고 합니다.)

1) Bootstrap ClassLoader

  • 3가지 중 최상위 클래스이다.
  • <JAVA_HOME>/jre/lib에 담긴 자바 라이브러리를 로딩한다.
  • Native C로 구현됨.

2) Extension ClassLoader

  • <JAVA_HOME>/jre/lib/ext 폴더에 담긴 자바의 확장 클래스파일을 로딩한다.
  • Java로 구현됨.

3) Application ClassLoader

  • -classpath(또는 -cp)폴더에 있는 클래스를 로딩한다.
  • Java로 구현됨.
  • 개발자가 직접 작성한 코드를 로딩한다.

위의 클래스들은 아래 3가지 원칙에 따라 동작한다.

  • Delegation Principle
    클래스로더는 상위 클래스로더로 로딩요청을 위임합니다. 부트스트랩 로더에서부터 로딩요청을 수행하고 하위 클래스로더로 요청을 넘깁니다.
  • Visibility Principle
    범위 규칙을 적용합니다. 하위클래스로더는 상위클래스로더의 클래스를 찾을 수 있지만 , 상위클래스로더는 하위클래스 로더가 로딩한 클래스를 사용할 수 없습니다.
  • Uniqueness Principle
    하위 클래스로더는 상위 클래스로더가 로딩한 클래스를 다시 로딩하지 않습니다.

2. 바이트 코드 검증 (Byte code verifier)

클래스 로더가 모든 실행 파일을 준비하면 이 파일의 코드가 올바른지 검증한다. 코드가 정해진 규칙에 따라 작성되었는지 등을 검증한다.

3. 기계어 코드로 변환

Java의 실행파일은 바이트코드이기 때문에 실행될 때 다시 한번 기계가 읽을 수 있는 형태로 인터프리터를 통해 해석된다.

JVM이 자바 실행파일을 기계어 코드로 변환하는 방식에는

  • 인터프리터
  • JIT (Just In Time) compiler
    가 있다.

GC와 Execution Engine

  • Garbage Collector : JVM은 Garbage Collector를 통해 메모리 관리 기능을 자동으로 수행한다. 애플리케이션이 생성한 객체의 생존 여부를 판단하여 더 이상 사용되지 않는 객체를 해제하는 방식으로 메모리를 자동 관리한다.
  • Execution Engine : Class Loader를 통해 JVM 내의 런타임 데이터 영역에 배치된 바이트 코드를 실행한다. 이 때, Execution Engine은 자바 바이트 코드를 명령어 단위로 읽어서 실행한다.

Runtime Data Areas

JVM이 운영체제 위에서 실행되면서 할당받는 메모리 영역이다. Class Loader에서 준비한 데이터들을 보관하는 저장소이다.

1. Method (Static) Area

JVM이 읽어들인 클래스와 인터페이스에 대한 Runtime Constant Pool, 멤버 변수(필드), 클래스 변수(Static 변수), 생성자와 메소드를 저장하는 공간이다.

2. Runtime Constant Pool

  • 메소드 영역에 포함되지만 독자적 중요성이 있다.
  • 클래스 파일 constant_pool 테이블에 해당하는 영역이다.
  • 클래스와 인터페이스 상수, 메소드와 필드에 대한 모든 레퍼런스를 저장한다.
  • JVM은 Runtime Constant Pool을 통해 해당 메소드나 필드의 실제 메모리 상 주소를 찾아 참조한다.

※ 메소드 영역/런타임 상수 풀의 사용기간 및 스레드 공유 범위

  • JVM 시작시 생성
  • 프로그램 종료 시까지
  • 명시적으로 null 선언 시
  • 구성 방식이나 GC 방법은 JVM 벤더마다 다를 수 있다.

3. Heap Area

  • JVM이 관리하는 프로그램 상에서 데이터를 저장하기 위해 런타임 시 동적으로 할당하여 사용하는 영역이다.
  • New 연산자로 생성된 객체 또는 객체(인스턴스)와 배열을 저장한다.
  • 힙 영역에 생성된 객체와 배열은 스택 영역의 변수나 다른 객체의 필드에서 참조한다.
  • 참조하는 변수나 필드가 없다면 의미 없는 객체가 되어 GC의 대상이 된다.
  • 힙 영역의 사용기간 및 스레드 공유 범위
    • 객체가 더 이상 사용되지 않거나 명시적으로 null 선언 시
    • GC(Garbage Collection) 대상
    • 구성 방식이나 GC 방법은 JVM 벤더마다 다를 수 있다.
    • 모든 스레드에서 공유한다.

4. Stack Area

  • 각 스레드마다 하나씩 존재하며, 스레드가 시작될 때 할당된다.
  • 메소드를 호출할 때마다 프레임(Frame)을 추가(push)하고 메소드가 종료되면 해당 프레임을 제거(pop)하는 동작을 수행한다.
  • 선입후출(FILO, First In Last Out) 구조로 push와 pop 기능 사용
  • 메소드 호출 시 생성되는 스레드 수행정보를 기록하는 Frame을 저장
  • 메소드 정보, 지역변수, 매개변수, 연산 중 발생하는 임시 데이터 저장
  • 기본(원시)타입 변수는 스택 영역에 직접 값을 가진다.
  • 참조타입 변수는 힙 영역이나 메소드 영역의 객체 주소를 가진다.

5. PC Register

  • Thread가 생성될 때마다 생기는 공간으로 Thread가 어떠한 명령을 실행하게 될지에 대한 부분을 기록한다.
  • JVM은 Stack-Base 방식으로 작동한다.
  • JVM은 CPU에 직접 Instruction을 수행하지 않고, Stack에서 Operand를 뽑아내 이를 별도의 공간에 저장하는 방식을 취하는데, 이러한 메모리 공간을 PC Register라고 한다.

6. Native Method Stack Area

  • 자바 외 언어로 작성된 네이티브 코드를 위한 Stack이다.
  • 즉, JNI(Java Native Interface)를 통해 호출되는 C/C++ 등의 코드를 수행하기 위한 스택이다.
  • 네이티브 메소드의 매개변수, 지역변수 등을 바이트 코드로 저장한다.

참고했습니다.

profile
어려운 것은 쉽게, 쉬운 것은 기억에 남게.

0개의 댓글