일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- Class Loader
- resilience4j
- AutoCloseable
- 4-way-handshake
- intelij
- 동작방식
- GC
- jetbrain
- java
- tcp
- 날짜쿼리
- 코딩테스트
- feign
- circuitbreaker
- Kotlin
- 람다표현식
- execution engine
- n+1
- zipWith
- closeable
- springboot
- webflux
- Hotspot VM
- Runtime data area
- try-catch
- jvm
- try-catch-finally
- optional
- try-with-resources
- wagon-ssh
- Today
- Total
JuBin's personal study blog
[JAVA] JVM 메모리 구조 정리 - 2 본문
JVM(Java Virtual Machine)
소프트웨어적으로 Java언어를 실행시키 위한, 자바 바이트 코드를 실행할 수 있는 주체, 또한 데몬이라고 합니다.
JVM 스펙은 각 벤더사마다 다르지만 표준은 존재합니다.
컴퓨터는 0과 1로 이루어진 기계어를 쓰는데 기계어는 사람이 쓰기에는 너무 어렵기 때문에 자바(Java)와 같은 고급언어를 사용해 프로그램을 작성하고, 컴파일러가 해당 언어를 기계어로 번역을 합니다. 자바 언어를 번역하는 컴파일러를 자바 컴파일러(javac.exe)라고 합니다.
물론, 자바의 경우, 컴파일러가 기계어로 바로 번역하진 않습니다. 운영체제나 하드웨어 마다 사용하는 기계어가 다르기 때문에 자바는 어느 운영체제나 하드웨어에서도 동일하게 동작하도록 자바 가상 머신(Java Virtual Machine; JVM) 상에서 동작을 합니다. 자바 컴파일러는 우리가 작성한 자바 소스 (.java) 를 클래스 파일 (.class)로 변환하고, JVM 이 클래스 파일을 해당 운영체제의 기계어로 변환을 해서 프로그램을 실행합니다.
● 한마디로 요약하자면(.java -> 네이티브 코드)
1. 개발자가 Java코드 작성(.java파일)
2. Java Compiler(javac)가 JVM이 해석할 수 있는 Java Byte Code로 컴파일(.java -> .class)
3. Class Loader가 JVM 내 Runtime Data Area(OS가 JVM에게 할당해준 메모리영역)에 .class파일을 적재
4. 이후 적재된 바이트코드를 실행엔진(Execution Engine) 인터프리터방식, JIT방식을 이용하여 바이트코드를 네이티브 코드(바이너리)로 변환
*JIT방식(Just-In-Time) : 인터프리터 방식은 한줄한줄 읽다보니 실행시간이 굉장히 깁니다.
따라서 JIT 컴파일러 방식은 실행하는 전체 코드를 컴파일하고 캐시합니다.
아래그림은 JVM의 전반적인 구성입니다.
- Method Area(=Class Area = Static Area) : 클래스, 변수, Method, static 변수, 상수 정보 등이 저장되는 영역이다.
초기화되는 대상을 저장하기 위한 메모리공간. GC대상이다. Heap영역과 다른점은 클래스 데이터를 위한 공간이다.(모든 Thread가 공유한다.) - Heap Area : new 명령어로 생성된 인스턴스와 객체가 저장되는 구역이다. 메소드 영역에 로드된 클래스만 생성이 가능하다. (Garbage Collection 이슈는 이 영역에서 일어나며, 모든 Thread가 공유한다.)
- Stack Area : Java Method 내에서 사용되는 값들(매개변수, 지역변수, 리턴값 등)이 저장되는 구역으로 메소드가 호출될 때 LIFO로 하나씩 생성되고, 메소드 실행이 완료되면 LIFO로 하나씩 지워진다.(각 Thread별로 하나씩 생성된다.)
- PC Register : CPU의 Register와 역할이 비슷하다. 현재 수행 중인 JVM 명령의 주소값이 저장된다.(각 Thread별로 하나씩 생성된다.)
- Native Method Stack : 다른 언어(C/C++ 등)의 메소드 호출을 위해 할당되는 구역으로 언어에 맞게 Stack이 형성되는 구역이다.
>> 메소드 영역과 힙 영역을 모든 쓰레드가 공유하고,
스택 영역과 PC 레지스터, Native method stack은 각각의 쓰레드마다 생성되고 공유되지 않는다.
Runtime Data Area의 Heap영역
Heap영역은 GC의 주요 대상입니다.(Stack영역과 Method영역도 GC의 대상)
Garbage Collection 하는 시간은 정확히 언제인지 알수는 없습니다. GC가 수행되는 동안 GC를 수행하는 쓰레드를 제외한 모든 쓰레드는 일시정지가 됩니다. 따라서 Full GC가 일어나면 장애로 이어질 수 있는 문제가 있다.
아래 그림은 Hotspot JVM의 Heap 구조의 전반적인 구성입니다.
Hotspot JVM Heap 구조는 Java 8 버전 전후로 구조가 바뀌었습니다. J
AVA 8 이전은 Permanent영역
↓
JAVA 8 이후는 Metaspace 영역으로 대체 되었습니다.
Hotspot JVM은 크게 Young Generation과 Old Generation으로 나누어져 있습니다.
Young Generation은 Eden 영역과 Suvivor 영역으로 구성되는데 Eden 영역은 Object가 Heap에 최초로 할당되는 장소이며 Eden 영역이 꽉 차게 되면 Object의 참조 여부를 따져 만약 참조가 되어 있는 Live Object이면 Suvivor 영역으로 넘기고, 참조가 끊어진 Garbage Object 이면 그냥 남겨 놓는다. 모든 Live Object가 Survivor 영역으로 넘어가면 Eden 영역을 모두 청소합니다
Suvivor 영역은 말 그대로 Eden 영역에서 살아남은 Object들이 잠시 머무르는 곳이다. 이 Suvivor 영역은 두 개로 구성되는데 Live Object를 대피시킬 때는 하나의 Survivor 영역만 사용하게 됩니다. 이러한 전반의 과정을 Minor GC(Young 영역 Garbage Collection)라고 합니다.
Young Generation에서 Live Object로 오래 살아남아 성숙된 Object는 Old Generation으로 이동하게 됩니다. 여기서 성숙된 Object란 의미는 애플리케이션에서 특정 회수 이상 참조되어 기준 Age를 초과한 Object를 말합니다. 즉, Old Generation 영역은 새로 Heap에 할당되는 Object가 들어오는 것이 아니라, 비교적 오랫동안 참조되어 이용되고 있고 앞으로도 계속 사용될 확률이 높은 Object들이 저장되는 영역입니다. 이러한 Promotion 과정 중 Old Generation의 메모리도 충분하지 않으면 해당 영역에서도 GC가 발생하는데 이를 Full GC(Major GC)라고 합니다.
Java 1.7 기준의 Perm 영역은 보통 Class의 Meta 정보나 Method의 Meta 정보, Static 변수와 상수 정보들이 저장되는 공간입니다. 이 영역은 Java 1.8부터는 Native 영역으로 이동하여 Metaspace 영역으로 변경되었습니다.(다만, 기존 Perm 영역에 존재하던 Static Object는 Heap 영역으로 옮겨져 최대한 GC 대상이 될 수 있도록 하였습니다.)
조금 더 1.7과 1.8 메모리 구조의 변경에 대해 설명하자면, Java 1.8에서 JVM 메모리의 구조적인 개선 사항으로 Perm 영역이 Metaspace 영역으로 전환되고 기존 Perm 영역은 사라지게 되었습니다. Metaspace 영역은 Heap이 아닌 Native 메모리 영역으로 취급하게 됩니다. (이 말은 기존의 Perm은 Heap 안에 존재하는 것으로 알 수 있다.) Native 메모리는 Heap과 달리 OS레벨에서 관리 하는 영역입니다.
출처, 참고: https://coding-start.tistory.com/205
'JAVA' 카테고리의 다른 글
[JAVA] String, StringBuilder, StringBuffer 차이점 (0) | 2021.04.14 |
---|---|
[JAVA] Checked Exception, UnChecked Exception (0) | 2021.04.12 |
[JAVA] MapStruct 사용하기(Object Mapping Library) (0) | 2021.03.19 |
[JAVA] 직렬화(Serialize)란? (0) | 2021.03.14 |
Maven Wrapper란(mvnw) (0) | 2021.01.05 |