일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- aws
- goroutine
- gochannel
- SAA
- Fargate
- docker
- Ingress
- BitBucket
- 도커
- SPF
- Lambda
- K8S
- 메일 인증 프로토콜
- Kubernetes
- SMTP
- serverless
- Datadog
- Certified Solutions Architect
- Java
- SAA-CO3
- JVM
- SAA-CO2
- EKS
- dMarc
- DKIM
- aws ses
- go
- Fluentbit
- awscli
- Today
- Total
DevOps Tasks
[JAVA ] JVM (Java Virtual Machine) Master 본문
JVM 이란?
JVM (Java Virtual Machine) 은 애플리케이션의 메모리를 동적으로 관리하므로 코드에서 메모리를 수동으로 할당하고 해제할 필요가 없다.
하지만, Java.lang.OutOfMemoryError 에러 메시지를 본 사람은 이 프로세스가 완벽하진 않다는 것을 알고 있다.
즉, 애플리케이션에 JVM이 할당할 수 있는 것보다 더 많은 메모리가 필요할 수 있다는 것이다.
또는 JVM이 메모리를 확보하기 위해 GC을 실행하면 애플리케이션 활동이 지나치게 길어져 지연 시간이 생길 수 있다.
JVM 이 GC를 통해 힙 메모리를 관리하고 JVM 메모리 관리에 가시성을 제공하는 주요 측정 항목과 로그를 알아본다.
측정 항목과 로그의 관계를 알아보고 OOM ( Out Of Memory )에 대한 더 많은 컨텍스트를 수집하여 메모리 관련 문제를 모니터링한다.
JVM의 메모리 영역은 Runtime Data Areas 안에서 기능에 따라 크게 5가지 영역으로 나뉘어 있다.
Method Area
Method Area는 보편적으로 Static (정적) 영역으로 부르는 메모리다.
애플리케이션을 실행 중에 Interface 나 Class를 사용하게 되면,
JVM 은 Class Loader를 사용해서 Interface와 Class의 Meta Data를 Method Area에 저장한다.
Class 가 로드되는 시점은 해당 Class 가 사용되기 위해 호출되는 시점이다.
Stack Area
Stack Area는 Method 가 호출될 시 할당되는 영역이다.
Method 호출 시 내부의 지역 변수도 Stack Area에 할당된다.
Heap Space에 객체를 올리고 해당 객체 데이터에 대한 참조 값이 할당되는 것이다.
예외적으로는 원시 타입 변수는 Stack 영역에 값 자체가 할당될 수 있다.
또한, 각 Thread는 하나의 Stack 영역을 할당받으므로 Thread 는 각자의 메모리 공간을 가지고 Method를 수행하는 것이다.
PC Register
JVM 은 한 번에 많은 Thread를 실행할 수 있어, 실행되는 각 Thread 별로 Program Counter Register를 가지고 있다.
Program Counter Register는 Memory에서 실행될 다음 명령어의 주소를 가진 프로세서의 레지스터를 말한다.
JVM의 PC Register는 JVM Thread 가 현재 실행 중인 Method의 명령을 담고 있는 주소를 포함하게 되고,
실행 중인 JVM Thread에 대해서 관리하는 관리자의 역할을 수행한다.
Native Method Stack
Native Method Stack 은 Native Method 로써 JAVA 이외의 언어로 작성된 Method를 지원하기 위한 스택이다.
이를 호출할 시 JVM Stack은 동작하지 않고, Native Method Stack을 활용하여 Frame을 push, pop 한다.
Heap Area
new 키워드를 통해서 객체를 생성하고 모든 객체와 해당 인스턴스 변수 및 배열이 저장되는 영역을 Heap이라고 한다.
해당 영역에서 생성된 객체들은 다른 객체의 필드 or Stack에 존재하는 다른 Method 들에 의해 참조될 수 있다.
참조 변수가 사라진다면 해당 객체는 필요 없는 것으로 간주하고 Garbage Collector에 의해서 할당이 해제된다.
Heap Area는 다시 해당 기능들에 따라 Eden, Servivor 0, Servivor 1, Old, Permenant 영역으로 세분화되어 Heap Area에서 참조하는 변수나 필드가 존재하지 않으면 GC의 대상이 된다.
Heap Area | 설명 |
Young Generation | Life Cycle 이 짧은 객체를 GC 대상으로 하는 영역이다. |
Eden | new 키워드를 통해 새로 생성된 객체가 위치한다. 정기적으로 GC 후 Live 객체들을 Survivor로 이동한다. |
Survivor 0 / Survivor 1 | 각 영역이 채워지게 되면, Live 객체는 비워진 Survivor 영역에 순차적으로 이동한다. |
Old Generation | Life Cycle 이 긴 객체를 GC 대상으로 하는 영역으로 Young Gen에서 마지막까지 살아남은 객체를 이동한다. |
Java 메모리 관리
JVM 이 시작되면 JVM 이 애플리케이션 Thread 가 액세스 해야 하는 객체를 저장하는 데 사용하는 메모리 영역인 Heap에 대한 메모리를 요청한다.
애플리케이션의 Heap 사용량이 최대 크기에 도달했지만 여전히 더 많은 메모리가 요구될 때 OutOfMemoryError가 발생하게 된다.
초기 Heap 크기는 물리적 메모리의 1/64로 잡히고
최대 Heap 크기는 실제 메모리의 1/4 사이즈로 잡힌다.
-Xms 50m -Xmx 100g = 최소 Heap을 50MB, 최대 Heap 을 100GB로 설정한다.
JAVA_OPTS="-Xms128m -Xmx512m"
# Percentage OpenJDK8 이상
JAVA_OPTS="$JAVA_OPTS -XX:MinRAMPercentage=50 -XX:MaxRAMPercentage=80"
JVM 은 GC를 실행하여 애플리케이션이 더 이상 사용하지 않는 객체에서 메모리를 확보하고 주기적으로 힙 사용량을 감소시킨다.
이로써 사용 중인 메모리의 할당을 해제시키지 않고 자동적으로 메모리를 확보한다.
JAVA_OPTS 들을 통해서 메모리 관리, 가비지 컬렉션, Thread 관리 등과 관련된 다양한 시나리오에서 사용할 수 있다.
애플리케이션의 요구 사항 및 환경에 따라 이런 옵션들을 조정하여 최적의 성능을 달성할 수 있다.
요구에 따라 해당 옵션들을 적절히 설정하여 JVM의 동작을 조정할 수 있다.
JAVA_OPTS | 설명 | 예시 |
-Xms | 힙 초기 크기를 설정 | -Xms512m |
-Xmx | 최대 힙 크기를 설정 | -Xmx2g |
-Xss | 스레드 스택의 크기를 설정 | -Xss1m |
-XX:MaxMetaspaceSize | 메타스페이스의 최대 크기를 설정 (Java 8 이상) |
-XX:MaxMetaspaceSize256m |
-XX:ParallelGCThreads | 병렬 가비지 컬렉션 스레드의 수를 설정 | -XX:ParallelGCThreads=4 |
-XX:+PrintGCDetails | 가비지 컬렉션 세부 정보를 출력 | -XX:+PrintGCDetails |
-XX:+DisableExplicitGC | 명시적 가비지 컬렉션 호출을 비활성화 | -XX:+DisableExplicitGC |
Out Of Memory (OOM) 관련 JAVA_OPTS
JAVA_OPTS | 설명 | 예시 |
-XX:MaxHeapFreeRatio | 힙 내의 비어있는 메모리의 최대 비율을 설정 | -XX:MaxHeapFreeRatio=70 |
-XX:MinHeapFreeRatio | 힙 내의 비어있는 메모리의 최소 비율을 설정 | -XX:MinHeapFreeRatio=40 |
-XX:NewRatio | Young 영역과 Old 영역의 비율을 설정 | -XX:NewRatio=3 |
-XX:MaxDirectMemorySize | ByteBuffer의 메모리 할당을 제한 | -XX:MaxDirectMemorySize=1g |
-XX:MaxRAM | JVM이 사용할 수 있는 최대 물리적 메모리 양을 제한 | -XX:MaxRAM=8g |
-XX:OnOutOfMemoryError | OOM 에러가 발생했을 때 실행할 명령을 설정 | -XX:OnOutOfMemoryError="kill -9 %p;exit 1" |
-XX:+HeapDumpOnOutOfMemoryError | OOM 에러 발생 시 힙 덤프 파일을 생성 | -XX:+HeapDumpOnOutOfMemoryError |
-XX:HeapDumpPath | OOM 시 생성된 힙 덤프 파일의 경로를 설정 | -XX:HeapDumpPath=/path/to/dumpfile.hprof |
Java Flight Recorder(JFR) 관련 JAVA_OPTS
JAVA_OPTS | 설명 | 예시 |
-XX:+UnlockCommercialFeatures | 상업용 JVM 기능을 잠금 해제 | -XX:+UnlockCommercialFeatures |
-XX:+FlightRecorder | Java Flight Recorder를 활성화 | -XX:+FlightRecorder |
-XX:StartFlightRecording | JVM 시작 시 Flight Recorder를 자동으로 시작 | -XX:StartFlightRecording=filename.jfr |
-XX:FlightRecorderOptions | Flight Recorder의 추가 옵션을 설정 | -XX:FlightRecorderOptions="stackdepth=64;memorysize=64m" |
'DevOps' 카테고리의 다른 글
메일 인증 프로토콜로 제로 스팸 메일 만들기 - SPF Part (0) | 2024.02.04 |
---|---|
[JAVA ] GC (Garbage Collection) Master (0) | 2024.01.31 |
Obsidian 알아보기 (0) | 2024.01.20 |
Git 이란? (0) | 2024.01.06 |
Simple 스크립트로 CI/CD Pipeline 최적화하기 (0) | 2024.01.06 |