새소식

반응형
Java

[JAVA] JVM 메모리 구조, 데이터 영역 ( Runtime Data Areas)

  • -
반응형

JVM의 구성요소 중, 데이터 영역에 대한 설명으로 아래의 내용들에 대해서 다루어 보도록 하겠다

  • Runtime Data Areas란
  • Runtime Data Areas의 구성 요소 
    • 스레드 별로 존재
      • PC Register
      • JVM Stack
      • Native Method Stack
    • 스레드 공유
      • Method Area
        • 상세 구조
      • Heap
        • 상세 구조 
        • Java8부터 달라진 점

Runtime Data Areas란

출처:(https://m.blog.naver.com/writer0713/221137837754)

JVM은 Java 컴파일러가 컴파일한 ByteCode를 ClassLoader를 이용해 메모리(RuntimeDataArea)에

실행 가능한 상태로 적재한다.

 

RuntimeDataArea는 JVM이 프로그램을 수행하기 위해 OS로부터 별도로 할당받은 메모리 영역이다. 


 

Runtime Data Areas의 구성 요소

출처 : (https://hongsii.github.io/2018/12/20/jvm-memory-structure/)

Runtime Data Area는 

PC Registers, JVM Stacks, Method Area, Heap, Native Method Stacks으로 구성된다. 

 

이 중 PC Register, JVM Stack, Native Method Stack은 각 스레드 별로 존재한다. 

각 쓰레드마다 서로 다른 메모리가 할당된다.

PC Register

  • 현재 수행 중인 JVM 명령의 주소
  • Thread가 생성될 때마다 생기는 공간으로 Thread가 어떠한 명령을 실행하게 될지에 대한 부분을 기록
  • JVM은 Stacks-Base 방식으로 작동하는데, JVM은 CPU에 직접 Instruction을 수행하지 않고, Stack에서 Operand를 뽑아내 이를 PC Register에 저장

JVM Stack

  • 각각 스레드가 시작될 때 생성
  • Stack Frame을 저장하는 스택
  • 메서드가 수행될 때마다 하나의 스택 프레임이 생성되어 해당 스레드의 JVM stack에 추가되고
    메서드가 종료되면 스택 프레임이 제거
    • Stack Frame은 Local Variable Array, Operand Stack, Constant Pool의 레퍼런스를 갖는다.

Native Method Stack

  • 자바 외의 언어로 작성된 네이티브 코드를 위한 스택
  • Java Native Interface를 통해 호출하는 C/C++ 코드를 수행하기 위한 스택

Heap과 Method Area는 각각의 스레드가 메모리를 공유한다.

Method Area는 클래스 데이터를 위한 공간이라면 Heap 영역이 객체를 위한 공간

Method Area는 변하지 않는 Constant 값들이 존재하기 때문에 각 스레드들이 메모리를 공유하더라도 문제가 없다.

Heap은 Garbage Collection의 대상이다. 

 

출처:(https://www.slideserve.com/kinsey/memory-management-case-study-jvm-clr)

Method Area

모든 Thread들이 공유하는 메모리 영역

프로그램 실행 중 클래스가 사용되면 JVM은 해당 클래스 파일을 읽어서 분석하여 클래스의 인스턴스 변수, 메서드 코드 등을 Method Area에 저장한다

Java 8 이전에는 Method Area를 PermGen(Permanat Generation Space)에 할당했다.
Java 8 이후에는 PermGen이 완전히 제거되어 Method Area는 Native Heap에 할당된다.

  • Type information
    • Type은 클래스와 인터페이스를 통칭하는 것으로 이해하면 된다
    • 클래스와 관련한 모든 정보
  • Constant Pool
    • 문자열 상수와 같은 리터럴 상수
    • 메서드와 필드에 대한 모든 Reference를 담고 있음 (Symbolic Reference) 
      즉, 어떤 메서드나 필드를 참조할 때, JVM은 런타임 상수 풀을 통해 메서드나 필드의 실제 메모리 상 주소를 참조하여 중복을 막는 역할
  • Field Information
    • Class 멤버 변수의 이름 및 데이터 타입, 접근 제어자에 대한 정보를 저장
  • Method Information
    • Class 멤버 메서드의 이름, 리턴 타입, 매개변수, 접근제어자에 대한 정보
  • Class Variable
    • static으로 선언되는 모든 클래스 변수
    • 이 변수는 모든 Instance에서 접근 가능하기 때문에 동기화 이슈가 발생할 수 있음
      Class Variable을 final로 선언할 경우에는 Constant Pool에 저장
  • Reference to ClassLoader & class Class
    • 특정 클래스를 로드한 클래스로더의 정보를 관리
    • Class object와 서로 양방향 접근을 하기 대문에 Class Object에 대한 참조 주소 값을 가진다
  • Method Table
    • Class의 Method에 대한 Direct Reference를 가진다고 보면 된다
    • Method Table을 이용해 Super Class에서 상속된 Method의 Reference까지 확인이 가능

Heap

  • JVM이 관리하는 프로그램 상에서 데이터를 저장하기 위해 런타임 시 동적으로 할당하여 사용하는 영역
  • new 연산자로 생성된 객체 또는 인스턴스와 배열을 저장
  • 힙 영역에서 생성된 객체와 배열은 스택 영역의 변수나 다른 객체의 필드에서 참조 
  • 참조하는 변수나 필드가 없다면 의미 없는 객체가 되어 GC의 대상이 된다

 

Heap의 구조는 JVM을 구현한 vender마다 다르다.

대표적으로 Oracle의 Hotspot JVM Heap구조를 살펴보도록 하겠다

출처:(https://mirinae312.github.io/develop/2018/06/04/jvm_memory.html)

GC가 발생하는 영역이며, 참조(레퍼런스)가 없는 객체들은 GC과정을 통해 메모리에서 제거된다.

Heap 영역 또한 내부적으로 여러 영역으로 나뉘어 있으며, 이는 객체의 lifecycle 및 GC와 연관되어 있다.

GC(Garbage Collection)와 관련된 내용은 다른 포스팅을 통해서 자세히 소개하도록 하겠다. 

 

Young Generation : Eden 영역과 Survivor영역으로 구성

  • Eden 영역
    • Object(객체)가 최초로 Heap에 할당되는 장소
    • 만일 Eden 영역이 가득 찼다면, Object의 참조 여부를 파악하고 LiveObject는 Suvrvior 영역으로 넘긴다
    • 모든 LiveObject가 Survivor영역으로 넘어간다면 Eden영역을 청소 (참조가 사라진 GarbageObject)
  • Survivor 영역
    • Survivor0과 Survivor1로 구성
    • Eden영역에 살아남은 Object들이 잠시 머무르는 곳이며 LiveObject들은 하나의 Survivor 영역만 사용
    • 이러한 전반적인 과정을 Minor GC

Old Generation 

  • Survivor1 또는 Survivor2 영역을 왔다 갔다 하는 과정에서 끝까지 살아남은 객체만이 Old 영역으로 이동
  • 보통 Old 영역은 Young 영역보다 크게 할당하며, 이러한 이유로 Old 영역의 GC는 Young 영역보다 적게 발생
  • Old Generation의 메모리가 충분하지 않으면 해당 영역에서 GC가 발생하는데 이를 Major GC

Permanent Generation 

  • Class의 Meta정보나 Method의 Meta정보, Static변수와 상수 정보들이 저장되는 공간, 흔히 메타데이터 저장 영역
  • 객체의 생명 주가기 길다고 판단되는 객체들을 이 영역에 할당하여 GC대상에서 제외를 하기 위해서 만들어진 영역
  • 주로 자바의 Class 객체들이나 문자열에 속한 String 객체들이 위치

대략적인 설명만으로는 위에서 설명한 Method Area와 겹친다는 생각이 든다

그래서 해당 내역을 찾아본 결과, Permanent Generation은 Method Area를 포함하고 있다 

(stackoverflow.com/a/60066513/9923340)

 

permGen OOM

위와 같은 Exception은 Heap의 구성 중, Permanent Generation의 memory가 부족한 현상이다

이러한 현상이 일어나는 요인으로는 아래의 것들이 있을 수 있다

  • static Object의 잘못된 사용
  • Class, Method Meta data의 증가

이러한 문제를 해결(?) 하기 위해서 Java8 버전에서부터는 Permanent Generation이 존재하지 않는다

해당 영역을 MetaSpace로 대체하였다

  • Static Object 및 상수화된 String Object를 heap 영역으로 옮김으로써, 최대한 GC가 될 수 있도록 수정
    (interned Strings and class static variables will be moved from the permanent generation to either the Java heap or native memory)
    java heap 또는 native memory라는 표현
  • Metaspace 영역은 Heap이 아닌 Native 메모리 영역으로 취급
    (Heap 영역은 JVM에 의해 관리된 영역이며, Native 메모리는 OS 레벨에서 관리하는 영역으로 구분)
  • Perm 영역 메모리 크기 옵션  -XX:PermSize / -XX:PermMaxSize,
    Metaspace 영역 메모리 크기 옵션 -XX:Metaspace / -XX:MaxMetaspaceSize

출처:(http://karunsubramanian.com/websphere/one-important-change-in-memory-management-in-java-8/)

 

포스팅을 위해 구글링을 하는 동안 헷갈렸던 부분을 다시 집으면

  • Method Area와 Permanent Generation의 차이가 뭐냐 (설명으로는 비슷해 보이는데) 
    • PermGen에 Method Area가 포함되어있다
  • Heap의 구성요소를 찾아보면 young, old, perm이 나오는데 Permanent Generation은 Heap의 구성요소가 맞냐

 

내가 이해한 그림 

 

참고 내역 :)

반응형
Contents

포스팅 주소를 복사했습니다

이 글이 도움이 되었다면 공감 부탁드립니다.