Programming Summary

Java) JVM이란? 본문

CS 공부

Java) JVM이란?

쿠키롱킹덤 2023. 9. 8. 20:29

1) JVM의 정의

자바는 썬 마이크로시스템즈 사의 제임스 고슬링에 의해 개발되었으며, Write Once Run AnyWhere라는 표어를 기반으로 제작되었다. JVM이란 Java Virtual Machine의 줄임말로, 이러한 자바 바이트코드를 실행할 수 있는 주체이다. 표어와 같이 JVM이 있다면 어떤 컴퓨터든 자바 코드를 실행 시킬 수 있다. 또한 자바 바이트 코드로 작성된 다른 언어도 JVM 위에서 실행이 가능하다.(대표적으로 코틀린이 있다)

간단하게 자바 초기 버전에 대해 살펴보면 JDK 1.0은 소형 가전 제품위에서 동작하도록 만든 코드였다.(심지어 카드에서도 돌아갔다) 근데 JVM의 특성상 무거울 수 밖에 없어 망했다. 그러다 웹에서 자바 코드를 돌릴 수 있게 되면서 다시 살아나게 되었다. 

 

2) JVM 구조

JVM 구조는 다음과 같다.

JVM 구조

들어가기 이전에 Java 언어로 작성된 .java 파일은 Java Compiler(javac)에 의해 Java Byte Code(.class 파일)로 컴파일 된 후 JVM에서 처리하게 된다. 이러한 JVM은 크게 세가지 구조로 나누어진다.

① Class Loader SubSystem

클래스 파일이 실행될 때를 생각해보자. 우리는 java.lang.*, javax와 같은 패키지들은 import를 하지 않아도 사용할 수 있다. 이는 Java에 기본적으로 내장되어 있는 패키지이기 때문이다. 이를 위해 동적 클래스 로딩 기능을 지원하는 Class Loader SubSystem이 만들어졌다. 클래스 로더 서브시스템은 다음과 같이 세가지로 나뉜다. 

  • Loading : 클래스 정보(FQCN)를 메모리에 로딩
    • BootStrap Class Loader
      • 가장 먼저 실행되는 클래스로더로 java를 로드한다. 또한 자바로 작성되지 않은 유일한 로더이다.(Java.*가 없으면 자바 코드를 실행할 수 없기 때문, Native C로 개발되어있다.)
    • Extension Class Loader
      • BootStrap Class Loader 이후에 실행되는 클래스 로더로 javax를 로드한다.
    • Application Class Loader
      • 마지막으로 실행되는 Class Loader로 우리가 사용하는 패키지를 로드한다.
  • Linking : 클래스 파일 검사, 정적 변수 기본값 저장
    • 로딩이 끝난 클래스가 JVM에서 실행되기 적잘한 형태를 갖추도록 도와준다.
    • Verify : 실제 바이트 코드가 올바른 문법을 갖고 있는가?
    • Preparation : 필요한 메모리를 할당하고 클래스 변수를 기본 값으로 초기화하는 단계
    • Resolution : 심볼릭 메모리 참조를 실제 메모리 참조로 변환
  • Initalization : 정적 변수 초기값으로 저장, static block 실행
    • 메서드는 실제 호출되기 전까지 로딩이 되지 않고, 추상 클래스를 먼저 로딩한다. 이후, 로딩의 필요성이 있을 때 구체적인 클래스를 로딩을 하게 된다. 이 의미는 우리가 필요로 할 때 로딩이 되므로 런타임 에러가 있어도, 로딩 되기 전까지는 실행이 가능하다는 의미이다.

Runtime Data Area

Runtime Data Area는 JVM이 프로그램을 수행하기 위해 OS로부터 할당받는 메모리 영역으로, 크게 5가지 영역으로 구분된다. 메소드 영역, 힙 영역, 스택, PC 레지스터, Native Method Stack이다.

PC Register, Stack, Native Method Stack은 Thread 별로 생성되고, Heap과 Method Area는 모든 쓰레드가 공유한다.

  • Heap Area(전체 쓰레드가 공유)
    • 객체(new로 만든 모든 것)와 배열이 생성되는 영역. GC가 자동 관리해준다.
    • JDK 1.7 버전까지는 Permanent Genration이 있어 Permanent Heap이 있었으나, 1.8버전 이후, PermGen이 없어지고 , MetaSpace(OS에서 관리하는 Native Heap에 할당)가 생기게 되어 없어졌다.
  • Method Area(전체 쓰레드가 공유)
    • 클래스 별로 런타임 상수풀, 필드 데이터, 메소드 데이터, 메소드 코드, 생성자 코드 등 힙 영역에 속하지 않는 나머지 코드들이 저장되는 공간이다.
  • Stack(쓰레드마다 존재)
    • 메서드 안의 지역변수들이 저장되는 영역이다.
    • 함수 호출이 있을 때마다 스레드마다 할당된 Stack Frame에 넣는다.
    • 스택을 활용하는 이유는 메서드가 끝나면 이전의 위치로 돌아가야 하기 때문이다. 해당 내용은 Stack Frame에 저장되어있다.
  • PC Register(쓰레드마다 존재)
    • 현재 수행중인 바이트 코드가 어디까지 실행되었는지를 저장한다. JVM 내의 기억장치이다.
    • 컨텍스트 스위치를 할 때 필요하게 된다.
    • CPU의 PC Register와는 다르게 Register-base가 아닌 Stack-base로 작동하게 된다. 
  • Native Method Stack
    • 자바 프로그램의 바이트 코드가 아닌 실제 실행할 수 있는 기계어로 작성된 프로그램의 호출을 저장하는 영역.
    • JNI(Java Native Interface)가 지원하기에 네이티브 방식의 메소드가 실행되면 Native Method Stack Area에 쌓이게 됨.

③ Execution Engine

바이트 코드를 Native Code로 변환해주는 Interpreter와 JIT 컴파일러, 그리고 JVM이 제공하는 굉장히 강력한 기능인 GC  이곳에 포함된다.

  • Interpreter
    • 바이트 코드를 한 줄씩 해석하여 실행하는 방식이다.
    • 한 줄씩 실행하다보니 속도가 느리다.
  • JIT(Just In Time) 컴파일러
    • 실제 실행되는 시점에 각 OS에 맞는 Native Code로 변환하여 실행 속도를 개선한 방식이다.
    • 인터프리터 방식을 사용하다 일정 기준을 넘어가면 JIT 컴파일러가 실행된다.
    • 자주 사용하는 기계어를 캐싱하고 있다가 바로 매칭해주는 방식으로 동작한다.
  • GC : Garbage Collector, 동적 할당된 객체들의 관리를 자동으로 해주는 역할
    • Serial GC : 단일 스레드에서 돌아가는 가장 기본적인 GC
    • Parallel GC : Young 영역을 멀티 스레드를 이용해서 heap을 관리, Java 8의 default GC
    • Parallel Old GC : Old 영역에도 멀티 스레드를 활용하여 heap을 관리
    • CMS GC : Concurrent Mark and Sweep GC, Mark와 Sweep을 할 때 애플리케이션 실행과 동시에 진행한 단계를 Concurrent하게 진행하여 STW 시간을 단축한 GC, G1 GC의 등장과 너무 많은 인수들로 인해 GC의 복잡성이 증가되어 Java 9에서 Deprecated
    • G1 GC : CMS를 개선하여 만든 GC, heap을 크기가 같은 area로 나누고 각 area 별로 eden, survivor, old와 같은 식으로 역할을 부여하여 heap을 관리하는 GC, Java 9+ default GC
    • Z GC : heap 영역이 크기가 다른 area로 나뉨. ms단위 STW 보장, 큰 메모리(16TB까지도 다룸)에 효율적인 GC, Java 11에서 새롭게 등장

 

바이트 코드 레벨까지 읽을 수 있으면 좋으니 공부해보자.

'CS 공부' 카테고리의 다른 글

DB) 트랜잭션 격리수준이란?  (1) 2023.09.22
DB) MVCC(Multi Version Concurrency Control)란?  (0) 2023.09.22
DB) 인덱스란?  (1) 2023.09.21
Programming) OOP란? 그리고 그 외 지식들  (1) 2023.09.05
GIT) Git이란?  (0) 2023.09.04