• 카테고리

    질문 & 답변
  • 세부 분야

    프로그래밍 언어

  • 해결 여부

    미해결

자바 메모리 구조에 대해 질문드립니다.

24.04.03 14:56 작성 24.04.04 10:29 수정 조회수 288

3

안녕하세요 영한님. 항상 양질의 강의로 지식을 공유해주시는점에 우선 감사하다는 인사부터 올리겠습니다.

자바 메모리 구조에 대해 강의를 들으면서 문득 궁금한 점, 스스로 지식 정리가 되지 않는 부분이 있어 질문드립니다.

 


우선 제가 알고 있는 사실입니다.

 

  1. JDK 스펙에서 메소드 영역의 구현 방식에는 제한하지 않기에 벤더마다 상이하다

  2. Java8 이전 오라클 핫스팟에선 이를 Permgen(Permanent Genration) 이라 명하였고 힙 메모리 안에 위치시켰다.

  3. 우리가 일반적으로 아는 static 변수 및 메소드, 클래스 정보, 런타임 상수 풀, String Pool 등이 이 메소드 영역 (Permgen)에 저장되었다.

  4. 하지만, Java8 이후 Permgen 의 고정된 메모리 이슈로(잦은 OOME) metaspace 라는 새로운 대체 공간을 만들고 이를 os영역인 Native memory 쪽에 두었다.

  5. java8 이후 현재, 기존의 Permgen 에 저장되던 클래스 메타 정보들 (constant pool)은 대체된 metaspace안에 저장되고 static 변수 및 메소드, String Pool(리터럴 String 및 interned String 저장 pool) 들은 Heap 영역으로 저장되게 변경되었다.

 


우선 제가 옳게 이해하고 있는지, 지식에 오류가 없는지 궁금하며 몇 가지 문의사항이 있습니다.

  1. 위 내용중 2)에서 Permgen을 힙 메모리 안에 두었다고 하지만 heap / non-heap 으로 구분하여 Permgen 은 non-heap 에 속한다 라고 설명하는 레퍼런스가 많습니다. Permgen이 non-heap 이라고 하는 이유가 비록 Permgen 이 논리적으로는 힙 메모리 안에 위치하지만, 일반적으로 gc 대상에선 제외되기 때문에 그런건지 아니면 실제로 물리적으로 분리된 공간이어서 non-heap 이라는건지 궁금합니다.


    (+ 지속적으로 찾아보니 Permgen 은 Heap 영역안에 특별한 공간 정도로 이해하면 될 듯 합니다. GC(major/full GC) 또한 동작한다고 하네요..! 이것과 별개로 metaspace의 경우도 더이상 사용하지 않는 클래스에 대해 메모리 회수가 일어난다고 합니다. 근데 이 metaspace 는 navtive 영역에 있는데 이걸 "gc가 동작하여 최적화한다" 라고 말할 수 있는 건지 아니면 그냥 Metaspace 자체에서 메모리관리를 한다고 봐야할지 궁금합니다..!)

  2. 궁극적으로 궁금한 부분인데요 메소드 영역 이라는 것에 대해 어떻게 이해하면 좋을지 의문입니다. 두 가지 정도로 생각하고 있는데,

    • 1. 메소드 영역 이라는 것은 JDK spec 에서 정의하고있는 하나의 추상화된 공간(인터페이스)이다. 이것이 과거엔 힙에 위치한 permgen으로 구체화 되었고 현재는 native 메모리에 위치한 metaspace로 구체화 되어 대체되었다. (메소드 영역이 상위 개념이다)

    • 2. 옛날 permgen, 현재의 metaspace 안에 특정한 데이터(클래스 메타데이터 같은)를 저장하는 별도의 공간이 있고 이를’ 메소드영역’ 이라고 한다.
      (메소드 영역이 하위 개념이다)

       

    • 메소드 영역과 permgen, metaspace 이들간의  카테고리 상 포함관계가 어떻게 되는지 개념이 궁금합니다.(1 번과 2번중에 어떤게 맞는지)

  3. 또한 현재 메소드 영역을 담당하는 metaspace 기준으로, static 변수, string pool 등은 Heap 영역에 저장되고(static 변수의 경우 heap 영역안의 static pool 안에) 클래스 정보, 런타임 상수 풀(constant pool) 등은 Metaspace 에 저장이 되는데 “메소드 영역에는 클래스정보, static 변수, 런타임 상수 풀이 저장된다” 라는 개념이 아직도 유효하고 옳은 개념인지 문의드립니다. 이게 말이 되려면 메소드영역이란 heap 영역의 일부 + metaspace 가 되어야 하기 때문입니다.

 

감사합니다.

답변 1

답변을 작성해보세요.

0

안녕하세요. 이상진님

1. Metaspace 자체에서 별도로 관리합니다.

2. 생각하신 1번 내용이 맞습니다.

3. 클래스 정보, static 변수, 런타임 상수풀은 metaspace에 저장됩니다.

여기서 static 변수가 어디에 저장되는가?에 논란이 있을 수 있는데요.

PermGen 영역이 metaspace로 대체되었기 때문에 static 변수 자체는 metaspace에 저장됩니다.

그런데 static 변수가 heap 영역에 저장된다는 이야기들이 있는데요. 아마도 다음과 같은 이유 때문이라 생각합니다.

- 기본형 static 변수: 클래스 데이터와 함께 메소드 영역에 저장됩니다. 변수가 기본형이므로, 값 자체가 직접 저장됩니다.

- 참조형 static 변수: 변수가 가리키는 객체의 참조(주소)는 메소드 영역에 저장되며, 객체 자체는 힙 영역에 위치합니다.

참조형의 경우 인스턴스의 참조값을 바라보는데, 이 참조값이 결국 힙 영역에 생기는 인스턴스이기 때문입니다.

정리하면 static 변수의 메모리 공간 자체는 metaspace에 생기고, 이것을 참조하는 인스턴스는 힙 영역에 생깁니다.

여기에 추가로 문자열 풀의 경우 Heap 영역에서 다루도록 변경되었습니다.

자바가 계속 변하고, 또 제가 JVM의 구현을 잘 아는 것이 아니어서, 정확한 정보가 아닐 수 있습니다.

관련해서 더 정확한 내용을 아시는 분들은 댓글 부탁드려요.

감사합니다.

이상진님의 프로필

이상진

질문자

2024.04.04

오.. 감사합니다! 저도 시간날때 틈틈이 찾아보고 공유할만한 정보가 있다면 공유하도록 하겠습니다. 답변 감사합니다!