위 영상을 보고 정리한 포스트
[영상 시청]
시스템에 여유 메모리가 없을때 시스템에서 과도하게 메모리를 사용하고 있는 프로세스를 희생하고 OS를 정상화한다. 이 역할을 하는것이 OOM Killer
Java로 서비스하고 있는 서버에서는 Java 프로세스가 가장 많은 메모리를 차지하므로 대부분 Java 프로세스를 죽일것이다.
Max Heap Size를 1.5GB로 설정했는데 OOM Killer가 죽인 Java 프로세스가 사용한 메모리는 4GB, 2.5GB의 알 수 없는 메모리 사용
Java 구동시 NativeMemoryTracking
옵션을 주면 jcmd 명령을 통해 자바 가상머신의 사용되는 메모리양을 측정할 수 있다.
원인을 찾아보자
Native Memory Leak이 쉽게 나타날 수 있는 부분
level 0 : 최적화 없이 기계어로 해석
level 1 : 최적화가 불필요하다고 느끼는 간단한 코드들, 프로파일링 정보 수집 x
level 2 : 제한된 최적화
level 3 : 프로파일링 모드로 정보 수집 후 최적화 진행
level 4 : 최대 최적화 진행
jvm의 컴파일러인 JIT컴파일러의 5단계중 마지막 단계의 컴파일러
C1 (Client Compiler) : 컴파일 시간은 빠르지만 최적화는 줄인다.
C2 (Server Compiler) : 컴파일 시간은 느리지만 최적화를 많이하여 연산이 빠르다. (서버에 적합)
Graal Compiler를 사용하기 위해선 UnlockExperimentalVMOptions라는 실험적 옵션을 사용하는 옵션을 줘야한다.
CPU 사용률이 적어지고 메모리 문제도 해결
JDK 버전에 릴리즈노트를 확인하며 실마리를 찾고 있지만 아직은 Graal을 사용중
트러블 슈팅
정답보단 문제 원인의 실마리를 찾아가는 과정
C1 컴파일러, C2 컴파일러에 대해 찾아보다가 궁금증이 생겼다.
C2 컴파일러만 최적화를 위해 코드캐시를 사용할까??
간단한 테스트코드를 만들고 -XX:+PrintCompilation
명령어와 -XX:+PrintCodeCache
명령어를 사용해 결과를 확인해봤다.
컴파일 로그에 대해 하나의 행을
n b c [message] 라고 가정해보면
n : 시작 부터 컴파일동안 걸린시간
b : 컴파일한 코드블록 정보
c : compile Tiere 정보
그리고 중간에 %가 보인다. 이는 코드캐시에 코드를 저장했다는 정보다. 아래 코드캐시 사용정보를 보면 사용량을 알 수 있다.
코드 캐시 이용 정보
'non-profiled nmethods': JIT 컴파일러가 프로파일링 정보를 이용하지 않은 메서드 코드를 저장하는 공간
(c2 Compiler)
'profiled nmethods': JIT 컴파일러가 프로파일링 정보를 이용한 메서드 코드를 저장하는 공간 (c1 Compiler)
'non-nmethods': JVM 내부 관련코드.