본문 바로가기

Programming Language/Java & Scala

Java8이상에서 MaxMetaspaceSize 설정, 반드시 해야할까?

지난글(Java 8 에서 사라진 maxPermSize, PermSize을 대체하는 옵션?)에서 Class의 Meta정보, Method의 Meta정보, Static변수와 상수정보를 저장하는 공간인 Permanent Heap에 대해서 이야기해 보았다. Java8부터 해당 Heap은 Native Memory영역으로 넘어갔으며 Native Memory상한까지 영역을 차지할 수 있으며, 그렇기에 Metaspace에 대한 옵션은 크게 주의를 가지고 설정할 필요가 없다고 적었다.

 

하지만, MaxMetaspaceSize를 정의하지 않은 상태의 특수한 상황이라면 어떨까?
지속적으로 class의 meta정보, static변수와 상수정보값이 늘어나는 경우에는 아래와 같이 끔찍한 일이 벌어질 것이다.

상기 application process의 memory는 아래와 같은 옵션으로 되어 있었다.

-Xms80g -Xmx80g -server -XX:+UseG1GC -XX:+DisableExplicitGC -XX:+UseStringDeduplication

아주 일반적인 java8의 g1gc를 사용한 option이다. 그런데 MaxMetaSpaceSize영역이 정해져 있지 않다보니 분명히 heap dump를 뜨거나 혹은 gc log를 봤을때는 무조건 80G만 영역을 차지하고 있는데도 불구하고 native memory의 사용영역이 무한히 늘어나서 Memory swap이 되기 일보직전까지 갔던것이다. swap이 시작되면 application은 현저할 정도로 속도가 느려지니 장애상황과 다름없다고 볼 수 있다.

 

상기와 같은 상황을 극복하기 위해 MaxMetaspaceSize를 추가해 보았다. 

-Xms80g -Xmx80g -server -XX:+UseG1GC -XX:+DisableExplicitGC -XX:+UseStringDeduplication -XX:MetaspaceSize=1024M -XX:MaxMetaspaceSize=1024M

앞으로 더 모니터링해야 하지만, java application을 위해 80Gb의 heap영역을 정해놓았고, 1Gb의 metaspace의 상한선을 선언했으니 앞으로는 81Gb까지 application process가 안정적으로 운영되어야 할 것이다.

 

추후 상기 모니터링 결과에 대해 정리해볼 것이다.