JVM (Java Virtual Machine)

yeoro·2021년 6월 9일
0
post-thumbnail

정의

  • 기술적 정의: JVM은 코드를 실행하고 해당 코드에 대해 런타임 환경을 제공하는 소프트웨어 프로그램에 대한 사양(Specification)이다.
  • 일반적 정의: 어떤 기기상에서 실행되고 있는 프로세스, 특히 자바 앱에 대한 리소스를 관리하고 통제하는 서버를 지칭한다.

기능

  • 자바와 운영체제 사이에서 중개자 역할을 하며 자바 프로그램이 어느 기기나 운영체제 상에서도 실행될 수 있도록 하는 것
  • 프로그램 메모리를 관리하고 최적화하는 것

클래스 로더(Class Loader)

클래스 로더는 JVM내로 클래스를 동적으로 로드하고, 링크를 통해 배치하는 작업을 수행하는 모듈이다.

계층구조


클래스 로더는 여러 클래스 로더끼리 부모-자식 관계를 이룬 계층적인 구조이다. 각 클래스 로더를 정리하면 다음과 같다.

부트스트랩 클래스 로더(Bootstrap Class Loader)

  • 최상위 클래스 로더로 유일하게 Java가 아니라 네이티브 코드로 구현되었다.
  • JVM이 실행될 때 같이 메모리에 올라간다.
  • Object 클래스를 비롯하여 Java API들을 로드한다.
  • rt.jar(runtime jar)와 $JAVA_HOME/jre/lib 경로에 위치한 코어 라이브러리를 로드한다.

익스텐션 클래스 로더(Extension Class Loader)

  • 기본 Java API를 제외한 확장 클래스들을 로드한다. (다양한 보안 확장기능 로드)
  • $JAVA_HOME/lib/ext 경로와 시스템 프로퍼티 java.ext.dirs에 언급된 경로를 확인한다.

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

  • 부트스트랩과 익스텐션 클래스 로더가 JVM 자체의 구성 요소를 로드한다면, 시스템 클래스 로더는 어플리케이션의 클래스들을 로드한다.
  • 사용자가 지정한 $CLASSPATH 내의 클래스들을 로드한다.
  • 이클립스의 Java Build Path에 추가한 라이브러리들을 로드한다.

사용자 정의 클래스 로더(User-Defined Class Loader)

  • 어플리케이션 사용자가 직접 코드상에서 생성하여 사용하는 클래스 로더이다.

위임모델


위임모델이란 처음 바이트 코드를 넘겨받은 클래스 로더가 필요한 클래스를 로드할 때 혹은 실행 엔진에서 명령어 단위로 바이트 코드를 실행하다가 처음으로 참조하는 클래스에 대해 클래스 로더에게 로드를 요청할 때 로드를 요청받은 클래스 로더는 다음과 같은 순서대로 요청받은 클래스가 있는지 확인한다.

1. 클래스 로더 캐시
이전에 로드된 클래스인지 클래스 로더 캐시를 확인한다.

2. 상위 클래스 로더
찾으려는 클래스가 클래스 로더 캐시에 없으면 상위 클래스 로더를 하나씩 거슬로 올라가며 확인한다.
이 때, 올라가는 도중에 클래스를 발견하더라도 부트스트랩 클래스 로더까지 확인한 후 해당 클래스가 존재하면 부트스트랩 클래스 로더에 있는 클래스를 로드한다.

3. 파일 시스템
부트스트랩 클래스 로더에도 해당 클래스가 없으면 로드를 요청받은 클래스 로더가 파일 시스템에서 해당 클래스를 찾는다.
파일 시스템에서도 클래스를 찾지 못하면 ClassNotFoundException가 발생한다.

가시범위 원칙(Visibility Principle)

계층 구조로 되어있는 클래스 로더에서 하위 클래스 로더는 상위 클래스 로더가 로드한 클래스를 볼 수 있지만, 상위 클래스 로더는 하위 클래스 로더가 로드한 클래스를 볼 수 없는 것을 의미한다.
가시 범위 원칙이 없다면 계층 구조가 없는 클래스 로더가 되고, 격리 레벨 없이 모든 것을 읽어와야 한다.

언로드(Unload) 불가

클래스를 로드하는 것은 가능하지만 반대로 언로드하는 것은 불가능하다.

이름 공간(Name Space)

각 클래스 로더들이 가지고 있으며, 로드된 클래스를 보관하는 공간이다.
클래스를 로드할 때 위임 모델을 통해 상위 클래스 로더들을 확인하는데 그 때 확인하는 공간이 이곳이다.
클래스들은 FQCN(Fully Qualified Class Name)을 기준을 보관되는데, FQCN이란 패키지명까지 포함되어있는 식별자를 뜻한다.

각각의 클래스 로더가 각자 이름 공간을 가지고 있기 때문에 FQCN이 같은 클래스라도 다른 클래스 로더가 로드한 클래스라면 다른 클래스로 간주한다.
이 특성을 이용하면 언로드를 대신해서 로드한 클래스 로더를 제거하면 마치 언로드한 것과 같은 효과를 줄 수 있다.

클래스 로드 과정


1. 로드: 클래스 파일을 가져와서 JVM의 메모리에 로드한다.
2. 검증: 클래스 로드 전 과정 중에서 가장 복잡하고 시간이 많이 걸리는 과정으로, 읽어들인 클래스가 자바 언어 명세(Java Language Specification) 및 JVM 명세에 명시된 대로 구성되어 있는지 검사한다.
3. 준비: 클래스가 필요로 하는 메모리를 할당한다. 필요한 메모리란 클래스에서 정의된 필드, 메소드, 인터페이스들을 나타내는 데이터 구조 등을 말한다.
4. 분석: 클래스의 상수 풀 내 모든 심볼릭 레퍼런스를 다이렉트 레퍼런스로 변경한다.
5. 초기화: 클래스 변수들을 적절한 값으로 초기화한다. (static 필드들을 설정한 값으로 초기화 등)


런타임 데이터 영역(Runtime Data Area)


JVM이 OS로부터 할당받는 메모리 영역이다. 각 스레드마다 PC 레지스터, JVM 스택, 네이티브 메소드 스택이 하나씩 생성되고 힙과 메소드 영역은 모든 스레드가 공유한다.

PC 레지스터(Program Counter Register)

스레드가 시작될 때 생성되며 각 스레드마다 하나씩 존재한다. 스레드가 어떤 부분을 어떤 명령으로 실행해야할 지에 대한 기록을 하는 부분으로, 현재 수행 중인 JVM 명령의 주소를 갖는다.

JVM 스택(JVM Stack)

[참고]

0개의 댓글