[Java] JVM, JRE, JDK

Junseo Kim·2021년 1월 26일
0

[Java]자바 기초

목록 보기
24/35
post-thumbnail

(출처: https://www.inflearn.com/course/the-java-code-manipulation)

JVM(Java Virtual Machine)

자바 가상 머신의 약자이며, 바이트 코드(.class)를 OS에 맞는(OS가 이해할 수 있는) 코드로 변환해준다.
OS에 맞는 코드로 변환해주기 때문에 JVM은 플랫폼에 종속적이다.

  • 바이트 코드를 어떻게 실행할 수 있는지에 관한 스펙
  • 바이트 코드를 OS에 맞는 코드로 변환
  • 정해진 스펙에 따라 구현하면 되기 때문에 구현체는 다양하다.(oracle, amazon, azul 등)
  • 네이티브 코드(각 OS에 맞는)로 바꿔서 실행해야하므로 플랫폼에 종속적이다.
  • 꼭 자바코드가 아니더라도, 바이트 코드로 컴파일된다면 JVM을 활용할 수 있다.

JRE(Java Runtime Environment)

JVM과 Library를 같이 제공하는 것(JVM + Library). 자바 애플리케이션을 실행하기 위한 것 자바 애플리케이션을 실행하기 위해서는 바이트 코드를 실행해야하므로 JVM이 들어있고, 핵심 라이브러리도 포함되어 있다. 하지만 개발하는데 필요한 툴은 제공되지 않는다.

  • JVM + Library
  • 자바 애플리케이션을 실행하기 위한 것
  • 개발하는데 필요한 툴은 포함되어있지 않으므로 JRE만으로 자바파일을 실행할 수 있지만, 컴파일을 할 수는 없다.(*oracle java 11버전부터는 아에 JRE는 따로 제공하지 않는다.)

JDK(Java Development Kit)

JRE와 개발하는데 필요한 툴을 합쳐놓은 것.(JRE + 개발 툴). 자바 언어로 작성하는 소스 코드는 플랫폼에 독립적이다. JDK에 포함되어있는 자바 컴파일러(javac)를 이용하여 자바 소스코드를 바이트코드로 컴파일 할 수 있다.

  • JRE + 개발 툴
  • 자바 소스코드는 플랫폼에 독립적이다.(Write Once Run Anywhere)

자바 애플리케이션 실행 과정

JVM 구조


(출처: https://www.inflearn.com/course/the-java-code-manipulation)

클래스 로더 시스템


(출처: https://www.inflearn.com/course/the-java-code-manipulation)

바이트 코드를 읽어서 메모리에 저장시킨다.

  • 로딩: 바이트 코드(.class)를 읽어와 바이너리 데이터를 만들고 메소드 영역에 클래스 정보(클래스 이름, 풀 패키지 경로, 부모 클래스 이름, 메소드, 변수 등)를 저장한다. 로딩 후 해당 클래스 타입의 Class 객체가 힙 영역에 저장된다.

    • 클래스 로더는 계층형 구조이다.(BootClassLoader - PlatformClassLoader - AppClassLoader) 어떤 클래스를 읽을 때, 제일 부모인 Bootstrap부터 읽을 수 있는지 확인한다. Bootstrap이 읽지 못하면 Extension이, Extension도 읽지 못하면 Application(본인)이 읽는다.
      *Application 로더도 읽지 못하면 ClassNotFoundException 발생
  • 링크: 레퍼런스를 연결하는 과정. Verify, Prepare, Resolve로 나눌 수 있다.

    • Verify: 바이트코드(.class) 형식이 유효한지 체크
    • Prepare: 메모리를 준비하는 과정. 클래스변수(static)와 기본값에 필요한 메모리를 준비
    • Resolve: 심볼릭 레퍼런스(실제 레퍼런스를 가리키고 있지 않은 상태)를 메소드 영역에 있는 실제 레퍼런스(메소드 영역에 저장되어있는 클래스정보)로 교체. Resolve과정은 반드시 이때 일어나는 것은 아니다.
  • 초기화: 클래스에 존재하는 static한 값들을 초기화한다. 링크의 Prepare을 통해 준비해놓은 메모리 영역에다가 static 변수 값을 할당하는 과정.

메모리

  • 메소드: 어떤 클래스가 사용되면 해당 클래스의 클래스파일(.class)를 읽어서 클래스 수준의 정보(클래스 이름, 풀 패키지 경로, 부모 클래스 이름, 메소드, 변수 등)를 저장하는 곳. 모든 쓰레드에서 사용가능. 다른 영역에서도 참조 가능한 정보들.
  • 힙: 객체(실제 인스턴스)를 저장. 모든 쓰레드에서 사용가능. 다른 영역에서도 참조 가능.
  • 스택: 쓰레드마다 런타임 스택을 만들고 메소드 호출 순서에 따라 스택에 쌓인다. 각 메소드 마다 메소드를 위한 메모리가 할당되며, 이 메모리를 작업 수행 시 지역변수, 매개변수, 연산 중간결과 등을 저장하는데 사용한다. 작업을 마치면 메모리가 반환되고 비워진다. 같은 쓰레드에서만 공유되며 다른 영역에서 참조 불가능
  • PC: 쓰레드 마다 현재 실행할 스택 위치를 가리키는 포인터. 같은 쓰레드에서만 공유되며 다른 영역에서 참조 불가능
  • 네이티브 메소드 스택: 쓰레드마다 네이티브 메소드 호출(네이티브 메소드는 JNI를 통해 사용된다.)할 때 사용하는 별도의 스택. 같은 쓰레드에서만 공유되며 다른 영역에서 참조 불가능

네이티브 메소드란? native라는 키워드가 붙어있고, java가 아닌 다른 언어(c, c++)로 구현된 메소드. JNI(Java Native Interface)는 네이티브 메소드의 인터페이스이며, 그 구현체는 네이티브 메소드 라이브러리이다.

실행 엔진

바이트 코드를 인터프리터가 이해. 반복적인 코드가 발생했을 경우는 JIT컴파일러로 보낸다.

  • 인터프리터: 바이트코드를 한줄씩 컴파일 & 실행하면서 네이티브 머신 코드로 바꿔주고 실행.
  • JIT(Just In Time): 바이트 코드를 네이티브 코드로 컴파일 해준다. 반복된 코드를 찾아 미리 바꿔둔다. 인터프리터가 한 줄씩 바이트코드를 컴파일하다가 반복되는 코드를 발견하면 JIT컴파일러에 의해 이미 변환된 코드를 바로 사용 -> 실행속도 향상
  • GC: 가비지 컬렉터. 더이상 참조되지 않는 객체를 모아서 정리한다.

0개의 댓글