잡동사니
A fatal error has been detected by the Java Runtime Environment 해결 본문
안녕하세요. yeTi입니다.
오늘은 자바 어플리케이션을 도커로 배포시 발생하는 A fatal error has been detected by the Java Runtime Environment
오류를 해결해보겠습니다.
현상
도커
로 Springboot
어플리케이션을 배포하는 상황에서 베이스이미지로 openjdk:12-alpine
을 사용했습니다.
쿠버네티스
에 배포 후 어플리케이션이 로드하는 과정에서 다음과 같은 오류가 발생했습니다.
#
# A fatal error has been detected by the Java Runtime Environment:
#
# SIGILL (0x4) at pc=0x00007fb82810e9bc, pid=1, tid=6
#
# JRE version: OpenJDK Runtime Environment (12.0+29) (build 12-ea+29)
# Java VM: OpenJDK 64-Bit Server VM (12-ea+29, mixed mode, sharing, tiered, compressed oops, serial gc, linux-amd64)
# Problematic frame:
# v ~StubRoutines::updateBytesCRC32
#
# Core dump will be written. Default location: Core dumps may be processed with "/usr/share/apport/apport %p %s %c %d %P %E" (or dumping to //core.1)
#
# An error report file with more information is saved as:
# //hs_err_pid1.log
Could not load hsdis-amd64.so; library not loadable; PrintAssembly is disabled
#
# If you would like to submit a bug report, please visit:
# http://bugreport.java.com/bugreport/crash.jsp
#
현상 파악
로그 분석
로그를 확인해보면 JRE
에서 SIGILL
오류가 발생했고 PrintAssembly
가 비활성화되어 hsdis-amd64.so
를 로드할 수 없다는 내용입니다.
이것만 가지고 정확히 어떤 부분에서 오류가 났는지는 알수가 없습니다.
검색
Could not load hsdis-amd64.so - Github에 따르면 Elasticsearch
프로젝트에서 해당 이슈 발생시 java
옵션에 -XX:UseSSE=2
를 추가하면 해결된다고 합니다.
Openjdk tests failed with msg 'Could not load hsdis-amd64.so; library not loadable; PrintAssembly is disabled' - Github에 따르면 java
옵션에 -XX:UseAVX=0
을 추가하면 해결된다고 합니다. 해당 이슈는 2019년 2월에 생성되어 2020년 4월에 close
됐습니다.
비슷한 이슈로 Set build JVM args - Github에 따르면 Kubernetes 환경에서 빌드 오류를 예방하려면 -XX:UseAVX=0
옵션을 추가해서 사용하라는 내용이 있습니다.
AVX enabled by default for Skylake even when unsupported - Github에 따르면 Skylake server CPUs
를 위해 UseAVX
옵션의 기본값이 2로 설정됐습니다.
분석
위에서 언급한 단어들을 확인해보겠습니다.
SSE(Streaming SIMD Extensions, SSE)
와 AVX(Advanced Vector Extensions)
는 x86 명령어 집합의 확장으로 SIMD명령어 집합중의 하나입니다.
이는 CPU에 따라서 지원하는 범위가 달라 CPU에 맞게 설정해줘야합니다.
그래서 현재 사용하고 있는 CPU를 확인해봤습니다.
Intel(R) Xeon(R) Silver 4214 CPU @ 2.20GHz x86_64
- Cascade Lake를 사용하고 있고 지원하는 명령어 집합은 avx2
, avx512f
, avx512dq
, avx512cd
, avx512bw
, avx512vl
, avx512
, sse
, sse2
, ssse3
, sse4_1
, sse4_2
를 지원합니다.
이와 같이 Cascadelake
아키텍처를 사용하고 있고, AVX
와, SSE
를 폭넓게 지원하고 있습니다.
참고적으로 Intel CPU의 아키텍쳐 변천사를 보면 Nehalem
, Sandybridge
, Ivybridge
, Haswell
, Broadwell
, Skylake
, Cascadelake
순으로 변화했고 Cascadelake
는 2019년 4월에 출시한 아키텍처입니다.
이제부터 JDK12
가 지원하는 CPU 및 AVX
, SSE
의 범위를 확인해보겠습니다.
enum Extended_Family {
// AMD
CPU_FAMILY_AMD_11H = 0x11,
// ZX
CPU_FAMILY_ZX_CORE_F6 = 6,
CPU_FAMILY_ZX_CORE_F7 = 7,
// Intel
CPU_FAMILY_INTEL_CORE = 6,
CPU_MODEL_NEHALEM = 0x1e,
CPU_MODEL_NEHALEM_EP = 0x1a,
CPU_MODEL_NEHALEM_EX = 0x2e,
CPU_MODEL_WESTMERE = 0x25,
CPU_MODEL_WESTMERE_EP = 0x2c,
CPU_MODEL_WESTMERE_EX = 0x2f,
CPU_MODEL_SANDYBRIDGE = 0x2a,
CPU_MODEL_SANDYBRIDGE_EP = 0x2d,
CPU_MODEL_IVYBRIDGE_EP = 0x3a,
CPU_MODEL_HASWELL_E3 = 0x3c,
CPU_MODEL_HASWELL_E7 = 0x3f,
CPU_MODEL_BROADWELL = 0x3d,
CPU_MODEL_SKYLAKE = CPU_MODEL_HASWELL_E3
};
위와 같이 OpenJDK 12
에서는 내부적으로 CPU
를 확인해서 AVX
의 사용수준을 정의하는데, 현재 Skylake
까지 지원하고 있습니다. 따라서 Cascadelake
에 대한 AVX
, SSE
설정이 맞게 되지 않을것이라고 추측할 수 있습니다.
OpenJDK13
, OpenJDK14
를 확인해본 결과도 Cascadelake
를 지원하지 않았습니다.
이어서 자바 옵션에 따른 명령어 확장 옵션의 설정을 확인해보겠습니다.
if (UseSSE < 4) {
_features &= ~CPU_SSE4_1;
_features &= ~CPU_SSE4_2;
}
if (UseSSE < 3) {
_features &= ~CPU_SSE3;
_features &= ~CPU_SSSE3;
_features &= ~CPU_SSE4A;
}
if (UseSSE < 2)
_features &= ~CPU_SSE2;
if (UseSSE < 1)
_features &= ~CPU_SSE;
if (UseAVX < 3) {
_features &= ~CPU_AVX512F;
_features &= ~CPU_AVX512DQ;
_features &= ~CPU_AVX512CD;
_features &= ~CPU_AVX512BW;
_features &= ~CPU_AVX512VL;
_features &= ~CPU_AVX512_VPOPCNTDQ;
_features &= ~CPU_VPCLMULQDQ;
_features &= ~CPU_VAES;
}
if (UseAVX < 2)
_features &= ~CPU_AVX2;
if (UseAVX < 1) {
_features &= ~CPU_AVX;
_features &= ~CPU_VZEROUPPER;
}
따라서 Intel(R) Xeon(R) Silver 4214 CPU @ 2.20GHz x86_64
가 지원하는 명령어 집합인 UseSSE=3
, UseAVX=2
로 설정하면 CPU가 지원하는 명령어 집합을 올바르게 사용할 수 있습니다.
해결
java
옵션에 -XX:UseSSE=3
, -XX:UseAVX=2
을 추가하여 지원하는 명령어 집합을 맞게 사용하도록 설정합니다.
'IT > Java' 카테고리의 다른 글
자바를 공부하는 방법 (0) | 2021.03.25 |
---|---|
VSCode ClassNotFoundException 해결 (0) | 2020.09.08 |
Solve ClassNotFoundException: org.junit.platform.engine.EngineDiscoveryListener (4) | 2020.03.24 |
Java 키워드 살펴보기 (0) | 2020.02.07 |
Java GC(Garbage Collection)의 이해 (0) | 2020.02.04 |