정의

자바 가상 머신

특징

  1. OS에 종속적이지 않다(CPU가 JAVA를 인식해서 사용한다).
  2. JAVA Source를 기계어로 컴파일 해주어 CPU가 *.JAVA를 인식할 수 있게 해준다.

Untitled

<aside> 📌 여기서 JAVA Compiler는 JDK를 설치하면 bin에 존재하는 javac.exe ❗javac를 이용하여 *.java*.class로 컴파일 가능 | javac *.java | ❗bytecode는 기계어가 아니라서 OS에서 실행되지 않는다. 또 다시 JVM이 이를 해석해서 기계어로 변환 ❗JVM을 구동시키는 명령프로그램은 JDK의 /bin에 존재하는 java.exe

</aside>

바이트 코드란?

정의

  1. JVM이 해석할 수 있는 언어 ⇒ java bytecode
  2. 명령어의 크기가 1바이트

특징

  1. 자바컴파일러에 의하여 바이너리 코드(1, 0으로 구성된 이진코드)로 변환

<aside> 📌 CPU가 이해하는 언어 = 바이너리 코드 바이너리 코드를 만드는 녀석 = JVM JVM이 알아먹는 언어 = 바이트 코드 바이트코를 알아먹는 녀석 = JAVAC (JAVA Compiler)

</aside>

JIT란?

정의

동적 번역

특징

인터프린터로 실행하다가 적절한 시점에 바이트 코드 전체를 컴파일하여 기계어로 변경 더 이상 인터프린팅하지 않는다. 기계어를 직접 실행

  1. 인터프린터 방식
  2. 정적 컴파일

한번 컴파일 된 기계어는 캐시에 보관하여 두번 컴파일되지 않는다.

만약 한번만 사용하는 코드라면 컴파일 하지 않는 인터프린팅이 유리 따라서 JIT는 메서드사용의 빈도와 일정 정도를 넣을 때 컴파일을 수행

Untitled

JVM의 구성요소?

Untitled

클래스로더?

정의

JVM내로 클래스파일 *.class를 로드, 링크를 통하여 배치하는 작업을 수행하는 모듈

클래스를 처음으로 참조할 때 , 해당 클래스를 로드하고 링크하는 역할

여기서 말하는 로딩 기능은 컴파일 타임이 아닌 클래스를 처음 참조할 때 즉, 런타임에 클래스 파일을 로딩, 연결, 초기화 작업이 이루어진다.

Loading의 상속관계/계층구조

Application classLoader extends Extension ClassLoader

Extension ClassLoader extends Bootstrap ClassLoader

클래스로더(클래스 로더 서브 시스템) 구성 : Loading 과정

<aside> 📌 ▪️**BootStrap ClassLoader : /$JAVA_HOME/jre/lib/rt.jar 기본 자바 API 로드, 가장 최우선 로드.** ▪️**Extention ClassLoader : /$JAVA_HOME/jre/lib/ext/*.jar Platform ClassLoader 라고 불림 확장 코어 클래스 파일 로드, JDK 확장 디렉토리에서 로드(JAVA Platform Extension 기능을 위한 기본 설치 모듈, Junit5에서도 보면 Platform 모듈이 존재 이걸로 인하여 Junit4와 호환이 된다. 비슷한 기능).** ▪️**Application ClassLoader : /$CLASSPATH CLASSPATH에 설정된 경로를 탐색하여 그곳에 있는클래스를 로딩하는 역할 , 사용자 정의 class파일 로드**

</aside>

Untitled

<aside> 📌 Class Loader의 가시제약 조건 일종의 범위룰이 적용되어 부모로더에서 찾지 못한 class는 자식로더에서 찾지 못한다(이는 Spring-boot에서도 찾아 볼 수 있는 Delegate방식인 것 같다. 확실하지는 않지만 Default Bean로드 과정에서 위와 비슷한 방식을 찾아볼 수 있다).

</aside>

<aside> 📌 Unload 불가 JVM상에 로드된 class는 지우는게 불가능

</aside>

클래스로더(클래스 로더 서브 시스템) 구성 : Linking 과정

<aside> 📌 ▪️검증(verify) : 바이트 코드가 적절한지 아닌지에 대하여 검증 ▪️준비(prepare) : 모든 정적변수의 메모리가 할당되며 기본 Default 값으로 할당(초기화는 아님) ▪️해석(resolve) :명확하게 정의되지 않은 메모리 참조를 메서드 영역에 있는 타입 직접 참조

</aside>

클래스로더(클래스 로러 서브 시스템) 구성 : initialize과정

실행 데이터 영역(Runtime Data Area)

Untitled

주로 5가지 영역으로 구분할 수 있다.

  1. 메서드 영역

  2. 힙 영역

  3. 스택 영역

  4. PC 레지스터

  5. 네이티브 메서드 스택 영역

  6. 메서드 영역

    1. 힙 영역

      • JVM이 관리하는 프로그램에서 데이터를 저장하기 위해 동적으로 할당하여 사용하는 공간
      • new 키워드로 생성된 객체, 인스턴스와 배열 저장
      • 힙에 생성된 객체, 배열은 스택영역의 변수나 다른 객체의 필드에서 참조 (스택 영역의 변수, 다른 객체의 필드)
      • 참조하는 변수, 필드가 없으면 GC의 대상이 되는 영역
      • 힙 영역의 분류

      Untitled

      <aside> 📌 JAVA 8, Permanent Area(PermGen)은 어디로? JAVA7에서 JAVA8로 넘어 오면서 JVM Hotspot의 PermGen영역은 사라졌다. String과 Static변수들은 모두 PermGen영역에서 JAVA Heap 영역으로 위치가 변경 되어서 Garbage Collector의 대상이 되고, 클래스의 메타정보들은 Metaspace영역으로 옮겨갔다. Metaspace는 Native Memory(off-heap) 공간으로 옮겨졌고, 기존에 PermGen 처럼 정적인 공간(사용자 설정 가능)으로 생겼는데 기본적으로 작게 할당이 되어 자주 out-of-memory 문제가 생긴 것을 해결할 수 있었다.

      요약

      1. permGen : 클래스 메타데이터를 읽고 해당 메타 데이터를 통해 객체를 생성하던 곳 (자바의 Heap이라곤 하지만 조금 속성이 다른 느낌, 기존에는 클래스 메타데이터 뿐만 아니라 static 변수와 상수 정보들이 저장, 그럼 이때는 GC대상이 아니였단 거임)
      2. OS, JVM Version 마다 각기 다른 default 값이라 out-of-memory가 자주 발생
      3. Java8부터 permGen을 없애고 Metaspace로 대체
      4. Metaspace는 클래스 메타데이터를 native메모리에 저장하고 부족하면 동적으로 늘려서 사용
      5. 기존 perm에 존재하던 static object는 heap으로 옮겨져 최대한 GC의 대상이 되도록함

      결론 heap에 있던 Perm을 Native 영역으로 빼고 이름은 Metaspace 즉, 클래스 메타정보만 담음

      </aside>

      [Hive] java.lang.OutOfMemoryError: PermGen space 에러

      Java 8, Permanent Area(PermGen)은 어디로 이동했나?

    2. 스택 영역

      • 쓰레드가 생성될때 메모리 영역이 같이 생성되며, 쓰레드가 종료되면 메모리에서 해제됨 (용량이 작다.)
      • 메서드를 호출할때 메서드 Stack Frame이 저장되는 영역(Stack Frame 내부에는 지역변수, 인자값, 리턴값 저장)
      • 스택 사용 과정
      • 저장 목록
      • Stack Frame
      1. PC 레지스터
      2. 네이티브 스택