기맹기 개발 블로그

[Java] JVM 구조 본문

Java

[Java] JVM 구조

기맹기 2023. 3. 5. 14:31

1. JVM, JRE, JDK

JVM (Java Virtual Machine)

  • 스택 기반의 VM
    • 명령어와 데이터가 모두 스택에 저장된다.
    • 장점 : 스택에 저장된 값의 메모리 주소를 사용하지 않기 때문에 명령어 크기가 작다.
    • 단점
      1. 상수 값에 비해 스택에서 값을 가져오는 작업이 느려서 성능이 떨어질 수 있다.
      2. 스택에 저장된 값이 메모리 상에 연속적으로 존재하지 않기 때문에 캐시 효율성이 떨어질 수 있다.
    • 레지스터 기반 VM은?
      • 레지스터에 저장된 값을 직접 사용하기 때문에 스택 기반 VM보다 빠르지만, 메모리 사용량이 증가한다.
  • 바이트코드를 OS에 의존적인 머신코드로 변환하여 실행한다.
  • JVM 자체는 바이트코드를 실행하는 표준이며, 특정 벤더에 의해서 구현된다.
  • JVM Specification (Java SE 11)

JRE (Java Runtime Environment)

  • JVM + 라이브러리
  • 자바 애플리케이션을 실행할 수 있도록 배포되는 단위
  • 핵심 라이브러리 및 JRE에서 사용하는 프로퍼티 세팅이나 리소스 파일을 포함한다.

JDK (Java Development Kit)

  • JRE + 개발 툴
  • Oracle JDK 11 이상 버전은 상용 목적일 때 유료이다.

 

2. JVM 구조

2-1. 클래스 로더

  • 바이트코드를 읽고 메모리에 적재하는 역할을 한다.
  1. 로딩 : 클래스를 읽어온다.
    • 메소드 영역에 FQCN(Fully Qualified Class Name), 메소드, 변수 등을 저장한다.
    • 해당 클래스 타입의 객체를 생성하여 힙 영역에 저장한다.
  2. 링크 : 레퍼런스들을 연결한다.
    1. Verify : 바이트코드 파일 형식이 유효한지 검증
    2. Prepare : 클래스 정적 변수와 기본값에 필요한 메모리
    3. (optional) Resolve : 심볼릭 메모리 (논리적) 레퍼런스를 메소드 영역에 있는 실제 레퍼런스로 교체한다.
  3. 초기화 : 정적 변수들을 초기화한다.

 

클래스 로더의 계층

  1. 부트스트랩 클래스 로더 : JAVA_HOME\\lib 에 있는 코어 자바 API 제공
  2. 플랫폼 클래스 로더 : JAVA_HOME\\lib\\ext 또는 java.ext.dirs 시스템 변수에 해당하는 위치에 있는 클래스를 읽는다.
  3. 애플리케이션 클래스 로더 : -classpath 또는 java.class.path 환경 변수의 값에 해당하는 위치에서 클래스를 읽는다.

 

2-2. 실행 엔진

  • 자바 인터프리터 : 바이트코드를 한줄씩 해석하고 실행한다.
  • JIT 컴파일러 : 인터프리터 효율을 높이기 위해서 반복되는 바이트코드를 네이티브 코드로 캐싱한다.
  • GC : 더 이상 참조되지 않는 객체를 모아서 정리한다.

 

2-3. 런타임 데이터 영역 (메모리)

  • 스레드 영역
    • PC 레지스터
    • 스택
    • 네이티브 메소드 스택
  • 공유 자원
    • 힙 영역 : GC에 의해 관리된다.
    • 메소드 영역 : 클래스 구조, 메소드, 생성자 코드, 런타임 상수 풀을 포함한다.
      • 런타임 상수 풀 : 클래스명, 인터페이스명, 메소드명, 필드명, 리터럴 상수 등을 포함한다.

2-4. 네이티브 메소드

  • JNI (Java Native Interface)
    • 자바 애플리케이션에서 C, C++, 어셈블리로 작성된 함수를 작성할 수 있도록 제공
    • native 키워드 이용
  • 네이티브 메소드 라이브러리 : C, C++로 작성된 라이브러리

 

3. 바이트코드

바이트코드의 구조는 아래와 같다.

컴포넌트 설명

매직 넘버 0xCAFEBABE
(클래스 파일임을 나타내는 4바이트 숫자)  
클래스 파일 포맷 버전 클래스 파일의 메이저/마이너 버전
상수 풀 클래스 상수들이 모여 있는 위치
(클래스명, 인터페이스명, 메소드명, 필드명 등)  
액세스 플래그 추상 클래스, 정적 클래스 등 클래스 종류를 표시
this 클래스 현재 클래스명
슈퍼클래스 슈퍼클래스명
인터페이스 클래스가 구현한 모든 인터페이스
필드 클래스에 들어 있는 모든 필드
메소드 클래스에 들어 있는 모든 메소드
속성 클래스가 지닌 모든 속성

 

클래스 파일 열어보기

역어셈블러를 이용해 class 파일의 상세 정보를 출력할 수 있다.

javap -c -v "class 파일 이름"

main()만 존재하는 클래스이며, javac에 의해 기본 생성자가 자동 추가된 것을 볼 수 있다.

 

  • invokespecial #1 : 슈퍼생성자들을 호출하고 객체를 생성한다.
  • ldc #7 : 상수 풀의 #7에 저장된 클래스 이름을 불러온다.
  • aload_0 : this 레퍼런스를 스택 상단에 올린다.
  • invokestatic #9 : 상수 풀의 #9에 지정된 정적 메소드인 “run”을 실행한다.

 


참조

'Java' 카테고리의 다른 글

[Java] JIT 메소드 인라인  (0) 2023.03.02
[Java] Java의 멀티스레드  (0) 2023.02.18
[Java] 제네릭 (Generic)  (0) 2023.01.12