[Java] JVM & 자바 동작원리

한호성·2024년 5월 7일
1

자바_기본개념

목록 보기
1/3

Introduction

자바 어플리케이션 성능 측정을 하려다 보니, 자바에 대해 모르는 부분이 많아서, 다시 한번 자바의 기본 동작원리와 어떻게 도는지 개념을 마지막을 정리하겠다.

한 2년전에 아직 개발을 막 시작했을 때도 같은 내용을 보고 정리했는데, 지금은 그 때보다 훨씬.. 이해하는 정도가 늘어나있는거 같다.
요번에 마무리로 깔끔하게 정리해놓고, 또 정리가 필요하면 나중에 시간이 흐르고, 더 성장해있을 때 정리해보도록 하자..

백기선 님의 자바 온라인스터디 깃헙를 기반으로 자바 개념을 순차적으로 정리해나갈 생각입니다.

JVM이란 무엇인가

  • Java Virtual Machine의 약자로, 컴파일된 자바 소스코드를 돌려주는 가상머신이다.
    (자바 어플리케이션이 수행되는 런타임 엔진을 의미)
  • JVM은 Bytecode를 읽어서 운영체제에 맞게끔 기계어로 번역해서 프로그램을 실행합니다.
  • 자바의 강점 중 하나로 꼽고 있으며, JVM으로 인해서 자바 코드들은 OS에 독립적이고,
    JVM은 OS 의존적입니다(OS에 맞는 JVM을 설치해줘야함) .

JVM 구성 요소

위의 그림을 보면

  • JVM으로 박스쳐져있는 부분이 JVM을 이루는 구성요소이고,
  • 그 위에는 자바 소스파일이 컴파일 되는것을 표현한 그림이다.

JVM은 크게 3가지 영역으로 생각할 수 있다.

  • ClassLoader
  • Runtime Data Area
  • Exectuion Engine

JVM의 정의는 "자바 어플리케이션이 수행되는 런타임 엔진"이다.
그렇기 때문에, JVM에서 표현되는 모든 것들은 런타임시 실행된다고 이해하면 된다.
각 영역에서 어떤 영역이며, 어떤 작업들이 이루어지는지 정리해보도록 하자.

classLoader

classLoader에 의해 컴파일된 class파일들로부터 데이터를 읽게 된다.
이 과정은 세가지 단계로 진행된다.

로딩 - 링크 - 초기화

로딩

  • 클래스 로더가 .class 파일을 읽고 그 내용에 따라서 "메소드 영역"(runtime data area 포함되어 있음)에 데이터(클래스의 메타데이터)를 저장

링크

  • 링크는 3가지 순서가 있음 (verification - preparation - Resolution)
  • verification : .class파일이 형식이 유효하지 확인하고
  • preparation: 클래스에 있는 static 변수들을 기본 값으로 메모리에 할당
  • Resolution: 해당 타입의 기호참조를 직접 참조로 변경 .. (?)

초기화

  • static 변수들의 값을 static 블록에서 선언한 값으로 지정
  • 클래스를 위에서부터 아래로 내려가면서 초기화 진행

기본적으로 클래스 로더의 종류

  • 부트스트랩 : JAVA_HOME/lib에 있는 코어 자바 API를 제공. 최상위 우선순위를 가진 클래스로더

  • 플랫폼 : JAVA_HOME/lib/ext 폴더 또는 java.ext.dirs 시스템 변수에 해당하는 위치에 있는 클래스를 읽는다.

  • 어플리케이션: 앱 classPath에 있는 곳에 클래스를 읽는다.

Runtime Data Area

메서드 영역 :

프로그램을 실행하는데 필요한 공통 데이터 관리. 이 영역은 프로그램의 모든 영역에서 공유한다.
클래스정보, static 영역, runtime 상수 풀

스택 영역 :

자바 실행시, 하나의 실행 스택이 생성된다. 각 스택 프레임은 지역변수, 중간 연산결과, 메소드 호출 정보들을 포함한다.
메소드가 종료되면 해당 스택 프렝미이 제거된다.
스택 영역은 쓰레드 별로 하나씩 생성된다.

힙 영역 :

개체와 배열이 생성되는 영역. GC가 이루어지는 주요 영역, 더이상 참조하지 않은 객체는 GC에 의해 제거된다.
클래스의 참조형 멤버변수는 각 인스턴스 값이 다르게 힙 영역에 존재하지만, 클래스의 메소드는 메소드 영역에 존재해서 공유하게 됩니다.

#cf) Heap 메모리의 old 영역에 메모리가 계속 쌓이게 되면, FULL GC가 발생하고, 모든 쓰레드들이 멈춰서 어플리케이션의 문제가 생길 수 있다.

PC Register 영역:

CPU가 instruction을 수행하는 동안 필요한 정보를 저장 ..(?)

Native Method Stakc:

Java 이외의 언어로 작성된 native코드를 위한 stack ..(?)

Exectuion Engine

실행엔진은 3가지로 구성되있다.

  • Interpreter
    • 바이트 코드를 라인단위로 읽어서 번역하고 실행
    • 반복되는 부분이 있어도, 계속 번역작업 수행
  • JIT Compiler
    • interpreter를 효율적으로 활용하기 위해서 사용
    • interpreter 반복적인 메소드 호출이 있을 때 JIT에서 해당 부분에 대한 네이티브 코드를 제공
      • Warm Up 단계에서 JIT Compiler가 자주 사용되는 것들을 만들게 되고 CPU사용량이 줄어드는 것을 알 수 있다.
      • 배포할 떄 Warm Up을 하고 난 후에 배포가 되도록 하는것이 좋다.
  • GC
    • 사용하지 않는 heap 메모리 영역 정리

컴파일

  • JDK에 포함되어있는 javac(Java Compiler)를 통해 .java 파일들을 jvm이 이해할 수 있는 bytecode(.class파일)로 바꾸게 됩니다.

바이트코드란 무엇인가

  • JVM이 이해할 수 있는 언어로 변환된 소스코드들이다
  • 코드의 명령어 크기가 1바이트라서, 바이트코드 라고 부른다.
  • 이것을 다르게 말하자면, JVM은 bytecode를 읽고 기계어로 변환한다. 그렇다면, 코틀린같은 언어들도 JVM 위에서 돌기 때문에, 코틀린으로 작성된 소스코드들도 bytecode로 변환해서 될 것이다. 즉 어떤 언어든 바이트코드로 바꿀 수 있다면, JVM을 통해 돌릴 수 있다는 이야기다..

정리

마지막으로 전체적인 그림으로 컴파일 타임과 런타임에 어떤 작업들이 이루어지는 간단하게 보자

몇년전에는 이 그림이 무슨말인가.. 했는데.. 이제는 그래도 어떤 영역이고, 어떤작업들이 이루어지겠구나 대략적으로는 알겠다. 많이 성장하긴 했구나란 생각이 든다..

Reference

https://github.com/whiteship/live-study/issues/1
https://jeongjin984.github.io/posts/JVM/

profile
개발자 지망생입니다.

0개의 댓글