반응형
해당 글에서는 JVM의 구성요소 중 하나인 Runtime Data Area에 대해 상세하게 알아보기 위해 작성한 글입니다.
💡 JVM의 동작과정에 대해 궁금하시면 아래의 글을 참고하시면 크게 도움이 됩니다.
1) JVM 메모리 영역(Runtime Data Area)
💡 JVM 메모리 영역(Runtime Data Area)
- 자바 프로그램이 실행될 때 사용되는 메모리 공간을 나타냅니다. 각각의 영역은 특정한 목적과 역할을 가지고 있습니다.
[ 더 알아보기 ]
💡 메모리 영역을 Runtime Data Area라고 부를까?
- 메모리 영역에서는 자바 프로그램을 실행하는 동안에 동적으로 할당하고 사용되는 데이터와 정보를 저장합니다. 그리고 프로그램의 실행 시간(runtime) 동안 필요한 데이터를 보관하고 관리하는 역할까지 수행합니다.
- 따라서 이 영역은 실행 데이터 영역들을 보관하고 관리하는 영역으로 Runtime Data Area라고 부릅니다.
2) JVM 메모리 영역(Runtime Data Area) 구조
💡 해당 부분에서는 JVM 내의 메모리 영역에 대해 종류들과 구조들에 대해 상세히 알아봅니다.
0. 요약
메모리 영역 | 저장 요소 | 스레드 공유 여부 | 생성 시점 | 소멸 시점 | 가비지 컬렉션 대상 |
메소드 영역(~ java 7) | 메소드, 클래스 정보 | 모두 공유 | JVM 실행 시 | JVM 종료 시 | 대상 아님 |
메타스페이스 영역(java 8 ~) | 메서드, 클래스 정보 + 클래스 메타데이터 | 모두 공유 | JVM 실행 시 | JVM 종료 시 | 대상 아님 |
힙 영역 | 객체, 배열 정보 | 모두 공유 | 프로그램 실행 시 | 프로그램 종료 시 | 대상 |
스택 영역 | 메서드 호출 시 사용한 메서드 인자값(파라미터), 지역 변수, 리턴 값, 임시값 정보 | 스레드 별로 생성, 공유하지 않음 | 스레드 시작 시 | 스레드 실행 종료 시 | 대상 아님 |
PC 레지스터 | 실행중인 명령어 주소 정보 | 스레드 별로 생성, 공유하지 않음 | 스레드 시작 시 | 스레드 실행 종료 시 | 대상 아님 |
네이티브 메소드 스택 영역 | 네이티브 메서드의 정보 | 스레드 별로 생성, 공유하지 않음 | 네이티브 메서드 호출 시 | 네이트브 메서드 실행 완료 시 | 대상 아님 |
1. 메서드 영역(Method Area) : ~ java 7
💡 메소드 영역(Method Area)
- JVM이 실행 중인 프로그램의 ‘메서드’와 ‘클래스 정보’를 저장하는 공간입니다.
- 해당 영역에서는 클래스 로더에 의해 로드된 바이트 코드, 상수 풀, 메서드와 필드 정보 등을 보관합니다.
- 해당 영역은 JVM이 실행될 때 해당 영역이 생성되며 JVM이 종료될때 메모리에서 해제가 됩니다.
- 정적 변수는 클래스 수준의 변수로 메서드 영역에 저장되어 모든 인스턴스가 공유할 수 있습니다.
[ 더 알아보기 ]
💡 PermGen 영역
- 클래스의 메타데이터를 저장하는 공간이며 JVM이 클래스와 메서드 등의 메타데이터를 로드하고 관리하는 데 사용됩니다.
- 해당 영역은 고정 크기로 할당되며 클래스 로딩 및 언로딩 작업이 빈번하게 발생할 경우 메모리 부족으로 인한 OutOfMemoryError가 발생할 수 있습니다.
- Java 8부터는 PermGen 영역이 제거되고, Metaspace 영역으로 대체되었습니다.
💡 메타 데이터
- 자바에서는 클래스의 구조, 메서드와 변수의 정보, 어노테이션 정보 등을 포함한 클래스와 관련된 정보를 메타데이터라고 합니다.
- 이러한 메타데이터는 JVM이 클래스를 로드하고 실행할 때 필요한 정보들로 메타스페이스 영역은 이러한 정보들을 효율적으로 저장하고 관리합니다.
1.1. 메소드 영역의 구조
영역 | 설명 |
상수 풀(Constant Pool) | - 클래스 파일의 상수 풀이 저장됩니다. - 문자열, 정수, 실수, 클래스 및 인터페이스에 대한 참조 등의 ‘상수 값들’을 저장합니다. |
메소드 정보(Method Information) | - 클래스의 ‘메소드들에 대한 정보’를 보관합니다. - 메소드의 이름, 시그니처, 접근 제어자 등을 포함합니다. |
필드 정보(Field Information) | - 클래스의 ‘필드들에 대한 정보’를 보관합니다. - 필드의 이름, 타입, 접근 제어자 등을 포함합니다. |
메소드 코드(Method Code) | - 메소드의 ‘바이트 코드’가 저장되는 공간입니다. - JVM은 메소드를 실행하기 위해 바이트 코드를 사용합니다. |
예외 테이블(Exception Table) | - 메소드 내에서 발생하는 ‘예외에 대한 처리 정보’를 보관합니다. - 예외 발생 시 어떤 예외 처리 루틴을 실행할지 결정하는 데 사용됩니다. |
1.2. 메소드 영역의 옵션 조절
💡 메소드 영역의 옵션 조절
- XX:PermSize와 XX:MaxPermSize는 Java 8 이전의 버전에서 사용되었으며, Java 8 이후부터는 메서드 영역이 제거되었습니다.
- Java 8 이후 버전에서는 XX:MetaspaceSize와 XX:MaxMetaspaceSize 옵션을 사용하여 메타스페이스 영역의 크기를 설정할 수 있습니다.
(* 해당 내용은 뒤에서 이어집니다)
옵션 | 설명 |
-XX:PermSize | 메소드 영역의 ‘초기 크기’를 지정합니다. 이 옵션을 사용하여 JVM이 시작될 때 메소드 영역이 할당받을 초기 크기를 지정할 수 있습니다. |
-XX:MaxPermSize | 메소드 영역의 ‘최대 크기’를 지정합니다. 이 옵션을 사용하여 메소드 영역이 할당받을 수 있는 최대 크기를 제한할 수 있습니다. |
-XX:ReservedCodeCacheSize | 메소드 코드의 저장 공간인 코드 캐시의 크기를 지정합니다. |
-XX:CompileThreshold | 메소드가 JIT 컴파일러에 의해 컴파일되기 전에 얼마나 자주 실행되어야 하는지를 지정합니다. |
-XX:+CMSClassUnloadingEnabled | 사용하지 않는 클래스를 메모리에서 언로드할 수 있는지 여부를 설정합니다. |
-XX:+UseConcMarkSweepGC | Concurrent Mark Sweep(CMS) 가비지 컬렉터를 사용하여 메소드 영역의 가비지 컬렉션을 수행할지 여부를 설정합니다. |
2. 메타스페이스 영역(Metaspace Area) : java 8 ~
💡 메타스페이스 영역(Metaspace Area)
- Java 8 이후부터 PermGen 영역의 대체로 도입된 영역으로 클래스 로딩, 메서드 수행, 리플렉션 등의 작업에서 사용되는 ‘클래스의 메타데이터’를 저장하는 공간을 의미합니다.
- PermGen 영역과 달리 클래스의 로딩 및 언로딩 작업이 발생하면 해당 영역에서 필요한 ‘메모리를 동적’으로 할당하거나 해제합니다. 그렇기에 PermGen 영역에서 발생하던 메모리 부족(OutOfMemoryError)과 관련된 문제를 해결할 수 있습니다.
- JVM의 힙 크기 설정과 별도로 관리 되므로 메타스페이스 영역에 충분한 메모리 할당을 하는 것이 중요합니다.
2.1. 메소드 영역과 메타스페이스 영역
💡 Java 8부터 메서드 영역에서 메타스페이스 영역으로 바뀌면서 무엇이 바뀐 걸까?
- 메서드 영역은 메서드의 바이트 코드뿐만 아니라 클래스와 인터페이스의 ‘메타데이터도 저장’하게 되었습니다.
- 이는 클래스의 구조, 필드 정보, 메소드 시그니처 등을 포함합니다. 이전에는 메소드 영역이 메소드의 코드만을 저장하는 영역이었지만, 이제는 더 많은 정보를 담고 있는 메타데이터 영역으로 사용됩니다.
💡 그래서 메타데이터을 저장을 하게 되면서 뭐가 좋아진 것일까?
1. 메서드 영역에 메타데이터를 포함하면 클래스의 구조, 필드 정보, 메소드 시그니처 등과 같은 중요한 정보를 한 곳에서 쉽게 액세스 할 수 있습니다.
- 이로써 개발자는 더 효율적으로 클래스와 인터페이스를 이해하고 사용할 수 있습니다.
2. 메타데이터를 메서드 영역에 저장함으로써 클래스의 로딩과 언로딩에 대한 관리가 용이해집니다. 이전에는 메서드 영역이 단순히 메소드의 코드만을 저장하는 용도로 사용되었지만, 메타데이터의 추가로 인해 클래스의 구조 변경 시에도 메소드 영역 전체를 갱신할 필요가 없어졌습니다.
- 이는 메모리 사용량을 줄이고, 클래스 로딩과 언로딩의 성능을 향상합니다.
3. 메타데이터를 메서드 영역에 포함하는 것은 리플렉션과 같은 기능을 지원하는 데에도 도움이 됩니다.
- 리플렉션은 실행 중에 클래스의 정보를 동적으로 검사하고 조작하는 기능으로, 메타데이터의 존재는 리플렉션을 통해 클래스와 관련된 작업을 보다 쉽게 수행할 수 있게 해 줍니다.
2.2. 메타스페이스 영역의 옵션 조절
💡 메타스페이스 영역의 옵션 조절
- XX:PermSize와 XX:MaxPermSize는 Java 8 이전의 버전에서 사용되었으며, Java 8 이후부터는 메서드 영역이 제거되었습니다.
- Java 8 이후 버전에서는 XX:MetaspaceSize와 XX:MaxMetaspaceSize 옵션을 사용하여 메타스페이스 영역의 크기를 설정할 수 있습니다.
옵션 | 설명 |
-XX:MetaspaceSize | 메타스페이스 영역의 ‘초기 크기’를 설정합니다. 이 옵션을 사용하여 JVM이 시작될 때 메소드 영역이 할당받을 초기 크기를 지정할 수 있습니다. |
-XX:MaxMetaspaceSize | 메소드 영역의 ‘최대 크기’를 지정합니다. 이 옵션을 사용하여 메소드 영역이 할당받을 수 있는 최대 크기를 제한할 수 있습니다. |
-XX:MinMetaspaceFreeRatio | 메타스페이스 영역에서 자유 공간의 최소 비율을 설정합니다. |
-XX:MaxMetaspaceFreeRatio | 메타스페이스 영역에서 자유 공간의 최대 비율을 설정합니다. |
3. 힙 영역(Heap Area)
💡 힙 영역(Heap Area)
- JVM에서 동적으로 할당된 ‘모든 객체’와 ‘배열’을 저장하며 ‘객체의 생명주기를 관리’하는 메모리 공간을 의미합니다.
- 해당 영역은 프로그램이 실행(Runtime)될 때 생성되며 프로그램이 종료될 때 메모리에서 해제됩니다
- 힙 영역은 ‘가비지 컬렉터’를 통해 자동으로 수행되며, 객체들은 ‘참조 변수’를 통해 접근하며 해당 참조변수가 없을 경우(사용되지 않는 경우) 가비지 컬렉터에 의해 메모리에 해제됩니다.
- 자바에서 중요한 메모리 영역이며 객체의 생성과 사용에 따라 성능과 메모리 사용량에 영향을 줄 수 있습니다.
3.1. 힙 영역의 구성요소
💡 힙 영역은 크게 Young Generation과 Old Generation으로 구성되어 있습니다.
💡 Young Genration
- 새로 생성된 객체들이 할당되는 공간을 의미합니다.
💡 Old Generation
- 일정 시간이 지나거나 메모리가 부족할 때, 살아남은 객체들이 이동하는 공간을 의미합니다.
힙 영역 요소 | 상세 요소 | 설명 |
Young Genration | Eden Area | - 새로 생성된 객체들이 할당되는 공간을 의미합니다 - 일정 시간이 지나서 살아남은 객체들은 두개의 Survivor 영역 중 하나로 이동합니다. |
Young Genration | Survivor Area | - Eden 영역 객체들 중 일정 시간 동안 살아남은 객체들을 보관하는 공간을 의미합니다. |
Old Genration | Tenured Area | - Young 영역에서 일정 시간이 지나거나 메모리가 부족할 때 살아남은 객체들이 이동하는 공간입니다. |
3.2. 힙 영역에서의 가비지 컬렉터
💡 가비지 컬렉터(GC, Garbage Collector)
- JVM에서 메모리 관리를 위해 사용이 되며 더 이상 참조되지 않는 객체들을 자동으로 탐지하고 해제하는 역할을 수행합니다. 이를 통해 개발자는 메모리 관리에 대한 직접적인 관여 없이도 안정적인 프로그램을 작성할 수 있습니다.
- 가비지 컬렉터는 메모리 관리를 효율적으로 처리하여 프로그램 실행 중에 메모리 누수를 방지하고 메모리 사용을 최적화합니다.
💡 Minor GC
- Young Generation에서 실행되는 가비지 컬렉션입니다. Young Generation은 새로 생성된 객체들이 할당되는 영역으로, 대부분의 객체는 짧은 수명을 가지고 있는데, 이 영역에서 객체들의 수명 주기를 추적하고 필요 없는 객체를 제거합니다.
💡 Major GC
- Old Generation에서 실행되는 가비지 컬렉션입니다. Old Generation은 오래된 객체들이 할당되는 영역으로, 객체들의 수명이 길어서 Young Generation에서 여러 차례의 가비지 컬렉션을 거치고 남아 있는 객체들이 최종적으로 이 영역으로 이동합니다.
-Major GC는 Old Generation에서 더 큰 규모의 가비지 컬렉션을 수행하여 메모리를 해제합니다.
4. 스택 영역(Stack Area)
💡 스택 영역(Stack Area)
- JVM에서 메서드 호출 시 사용한 메서드의 인자 값(파라미터), 지역 변수, 리턴 값, 임시 데이터 등이 스택에 저장됩니다.
- 해당 영역은 스레드가 시작될 때 생성되고 스레드의 실행이 종료될 때 메모리에서 해제됩니다.
- 해당 영역은 각 스레드마다 별도의 스택 영역이 생성이 됩니다. 따라서 모든 스레드와는 공유가 되지 않고 자신만의 영역을 갖습니다.메서드가 호출될 때마다 스택 프레임(Stack frame)이 생성되며 메서드의 매개변수, 지역 변수, 리턴 주소 등이 후입선출(LIFO, Last-In-First-Out) 구조로 동작하여 스택 프레임에 저장됩니다.
- 메소드의 실행이 종료되면 해당 스택 프레임은 제거됩니다.
[ 더 알아보기 ]
💡 스택 프레임(Stack Frame)
- 메소드가 호출될 때 생성되는 메모리 공간입니다.
- 각각의 메소드 호출은 스택 프레임을 만들며, 스택 프레임에는 해당 메소드의 매개변수, 지역 변수, 복귀 주소 등이 저장됩니다. 메소드의 실행이 종료되면 해당 스택 프레임은 제거됩니다.
💡 스택 영역의 후입선출(LIFO) 구조
- 가장 최근에 호출된 메서드가 가장 먼저 실행을 완료하고 스택에서 제거됩니다. 이러한 구조 때문에 메서드의 재귀 호출과 같은 작업을 처리할 수 있습니다.
5. PC 레지스터(PC Register)
💡 PC 레지스터(PC Register)
- JVM의 메모리 영역 중 하나로 각 스레드마다 현재 ‘실행 중인 명령어의 주소’를 저장하는 메모리 공간을 의미합니다.
- 해당 영역은 스레드가 시작될 때 초기화 되며 스레드가 종료되면 메모리에서 해제됩니다.
- PC 레지스터는 프로그램 카운터(Program Counter)라고도 불리며, 현재 실행 중인 명령어의 위치를 가리키는 역할을 합니다. 스레드가 다음 명령어를 실행하기 위해 PC 레지스터를 참조합니다.
- 스레드마다 독립적으로 관리되며, 각 스레드는 자신의 PC 레지스터를 가지고 있습니다. 이를 통해 다중 스레드 환경에서 동시에 여러 명령어를 실행할 수 있습니다. 스레드가 다른 스레드로 전환될 때, 해당 스레드의 PC 레지스터 값이 로드되어 다음 명령어를 실행합니다.
- 독립적으로 명령어의 실행 흐름을 제어하고, 다른 스레드로 전환될 때 해당 스레드의 PC 레지스터 값이 로드되어 실행이 진행됩니다.
6. 네이티브 메서드 스택 영역(Native Method Stack Area)
💡 네이티브 메소드 스택 영역(Native Method Stack Area)
- JVM의 메모리 영역 중 하나로 ‘자바 이외의 언어로 작성된 네이티브 코드’를 실행하는 영역을 의미합니다.
- 해당 영역은 네이티브 메소드 호출 시 생성되며 네이티브 메서드의 실행이 완료되면 메모리에서 해제됩니다.
- 네이티브 메서드의 호출과 반환에 필요한 데이터를 저장합니다. 이 영역은 스택 프레임(Stack Frame)이라고도 불리는 작은 메모리 블록들로 구성되어 있으며, 네이티브 메소드 호출 시 스택 프레임이 생성되고, 메소드의 실행이 완료되면 스택 프레임이 제거됩니다.
- JVM이 자바 프로그램에서 네이티브 메서드를 실행하는 데 필요한 자원을 제어하고 최적화하는 데 사용됩니다. 각 스레드마다 독립적으로 생성되며, 네이티브 메소드 호출이 발생할 때 해당 스레드의 스택 영역에 스택 프레임이 생성됩니다.
💡 [참고] 해당 글은 다음 글인 '가비지 컬렉터(GC)'와 이어집니다.
오늘도 감사합니다. 😀
반응형
'Java > 이론 및 문법' 카테고리의 다른 글
[Java] API 캐시와 세션 이해하기 (1) | 2023.10.22 |
---|---|
[Java] JVM(Java Virtual Machine) 이해하기 -3 : 가비지 컬렉터(GC, Garbage Collector) (0) | 2023.10.09 |
[Java] JVM(Java Virtual Machine) 이해하기 -1 : 동작 과정 (0) | 2023.10.06 |
[Java] 반복문의 제어문(Control Flow Statement) 이해하기 (0) | 2023.10.03 |
[Java] 사용 목적에 따른 반복문(Loop) 이해하기 (0) | 2023.08.27 |