JAVA의 메모리? JAVA의 메모리 구조에 대한 이해

JAVA 메모리 구조와 GC 등에 대한 이해

  • JAVA의 메모리 구조에 대해서 이해해보는 시간을 가져본다.

JVM이란?

JAVA의 메모리 구조에 대해서 설명하기 전에 JVM이 무엇인지 알아야 한다.
JVM은 Java Virtual Machine의 약자로, 자바 가상 머신이라고 불린다.
자바의 운영체제 사이에서 중개자 역할을 수행하며, 자바가 운영체제에 구애 받지 않고 프로그램을 실행할 수 있도록 도와주는 역할을 수행한다.
또한, GC(Garbage Collector)를 사용한 메모리 관리도 자동으로 수행하며 다른 하드웨어와 다르게 레지스터 기반이 아닌 스택 기반으로 동작한다.

image

먼저, 자바 컴파일러에 의해 자바 소스 파일은 바이트 코드로 변환된다. 그리고 이러한 바이트 코드를 JVM에서 읽어 들인 다음에 이것을 복잡한 과정을 거쳐서 어떤 운영체제든간에 프로그램을 실행할 수 있도록 만든다.

만약 자바 소스 파일은 리눅스에서 만들어졌고, 윈도우에서 이 파일을 실행하고 싶다면 윈도우용 JVM을 설치하기만 하면 되는 것이다! 여기서 JVM은 운영체제에 종송적이라는 특징을 알 수 있다.


JVM 메모리 구조

이제 JVM이 무엇인지, 자바 프로그램의 실행 단계에 대해서 간략하게 알아보았으니 JVM의 구체적인 수행 과정에 대해서 정확히 어떤 구조를 가지고 있고 어떻게 동작을 하는지 알아보자.

아래는 자바 프로그램의 실행 단계로, JVM은 크게 4가지의 구조로 나누어 볼 수 있다.

  • Garbage Collector
  • Execution Engine
  • Class Loader
  • Runtime Data Area

image

다시 한 번 언급하자면, 자바 소스 파일은 자바 컴파일러에 의해서 바이트 코드 형태인 클래스 파일이 된다. 그리고 이 클래스 파일은 클래스 로더가 읽어들이면서 JVM이 수행된다.

Garbage Collector

Garbage Collector(GC)는 힙(heap) 메모리 영역에 생성된 객체들 중에서 참조되지 않은 객체들을 탐색후 제거하는 역할을 한다. 이때, GC가 역할을 하는 시간은 언제인지 정확히 알 수 없다.

Execution Engine

클래스 로더를 통해 JVM 내의 Runtime Data Area에 배치된 바이트 코드들을 명령어 단위로 읽어서 실행한다. 최초 JVM이 나왔을 당시에는 인터프리터 방식이라고 하는데 속도가 느리다는 단점이 있었기 때문에 JIT 컴파일러 방식을 통해 이 점이 보완되었다.
JIT는 바이트 코드를 어셈블러 같은 네이티브 코드로 바꿈으로써 실행이 빠르지만 역시 변환하는데 비용이 발생했다. 이 같은 이유로 JVM은 모든 코드를 JIT 컴파일러 방식으로 실행하지 않고, 인터프리터 방식을 사용하다가 일정한 기준이 넘어가면 JIT 컴파일러 방식으로 실행한다.

Class Loader

JVM 내로 클래스 파일을 로드하고, 링크를 통해 배치하는 작업을 수행하는 모듈이다. 런타임 시에 동적으로 클래스를 로드한다.

Runtime Data Area

JVM의 메모리 영역으로 자바 애플리케이션을 실행할 때 사용되는 데이터들을 적재하는 영역이다.
이 영역은 크게 아래와 같이 나눌 수 있다.

  • Method Area
    • 모든 쓰레드가 공유하는 메모리 영역. 메소드 영역은 클래스, 인터페이스, 메소드, 필드, Static 변수 등의 바이트 코드를 보관한다.
  • Heap Area
    • 모든 쓰레드가 공유하며, new 키워드로 생성된 객체와 배열이 생성되는 영역이다.
    • 또한, 메소드 영역에 로드된 클래스만 생성이 가능하고 Garbage Collector가 참조되지 않는 메모리를 확인하고 제거하는 영역이다.
  • Stack Area
    • 메서드 호출 시마다 각각의 스택 프레임(그 메서드만을 위한 공간)을 생성한다.
    • 메서드 안에서 사용되는 값들을 저장하고, 호출된 메서드의 매개변수, 지역변수, 리턴 값 및 연산 시 일어나는 값들을 임시로 저장한다.
    • 메서드의 수행이 끝나면 프레임별로 삭제한다.
  • PC Register
    • 쓰레드가 시작될 때 생성되며, 생성될 때마다 생성되는 공간으로 쓰레드마다 하나씩 존재한다.
    • 쓰레드가 어떤 부분을 무슨 명령으로 실행해야할 지에 대한 기록을 하는 부분으로 현재 수행중인 JVM 명령의 주소를 갖는다.
  • Native Method Stack
    • 자바 외 언어로 작성된 네이티브 코드를 위한 메모리 영역이다.