https://www.baeldung.com/jvm-parameters
자바를 실행할 때는 JVM(Java Virtual Machine)이라는 가상머신을 이용하게 된다. 이 JVM을 이용하다가 여러가지 문제에 부딪힐 때가 많은데 이를테면 메모리 문제라든지 테스트 환경에서 콘솔을 못 쓰는 문제라든지 가비지 컬렉션과 관련된 문제라든지 여러가지가 있다.
성능에 관련된 문제 중에 가장 흔한 문제는 애플리케이션이 요구하는 만큼 힙 메모리 초기화를 못할 때 일어나는 문제이다. 힙 사이즈의 최소 값과 최대 값을 줌으로써 이 문제를 해결할 수 있다. 아래는 힙 사이즈를 주는 방법이다.
-Xms<heap size>[unit]
-Xmx<heap size>[unit]
여기서 unit
이란 것은 힙사이즈에 의해 표기되는 메모리에 초기화될 unit
을 나타낸다. unit
은 GB일 경우 'G', MB일 경우 'M', KB일 경우 'K' 로 표기될 수 있다.
이를테면 최소 2GB 메모리에서 최대 5GB 메모리까지 JVM에 할당하고 싶다면, 다음과 같이 작성하면 된다.
-Xms2G -Xmx5G
자바8부터, Metaspace의 사이즈는 정의되지 않았다. 전역 리미트에 걸리게 되면, JVM은 자동으로 이 사이즈를 늘려나간다. 하지만, 불필요한 불안정성을 극복하기 위해서, 다음과 같이 Metaspace를 조정할 수 있다.
-XX:MaxMetaspaceSize=<metaspace size>[unit]
metaspace
에 대해서는 여기 링크에 잘 나와있다.
metaspace size
라는 것은 말 그대로 metaspace
에 들어갈 메모리의 양을 표기하는 것이다. 오라클의 가이드라인에 따르면, 총 사용 가능한 메모리 다음에, 가장 영향력 있는 요소는 Young Generation
에 대한 힙의 양이다. 기본 값으로는 1310MB가 들어가있고, 최대 값으로는 제한이 없다.
힙은
Young Generation
과Tenured Generation
으로 나누어져있다고 한다. 참고 링크
다음과 같이 할당해줄 수 있다.
-XX:NewSize=<young size>[unit]
-XX:MaxNewSize=<young size>[unit]
안정적인 앱을 위해서 올바른 가비지 콜렉션 알고리즘은 필수적이다. JVM은 4가지 종류의 가비지 콜렉션 구현이 있다.
아래와 같은 파라미터를 이용함으로써 구현이 선언될 수 있다.
-XX:+UseSerialGC
-XX:+UseParallelGC
-XX:+UseParNewGC
-XX:+USEG1GC
각 가비지 콜렉션에 대한 자세한 내용은 여기에서 살펴볼 수 있다.
어플리케이션 상태에 대한 엄격한 모니터링을 위해, JVM 가비지 콜렉션 성능을 항상 체크해야 한다. 가장 쉬운 방법은 가비지 콜렉션 활동 로그를 사람이 읽기 쉬운 형태로 표기해주는 것이다. 아래의 파라미터를 통해서 가비지 콜렉션 활동 로그를 남길 수 있다.
-XX:+UseGCLogFileRotation
-XX:NumberOfGCLogFiles=< number of log files >
-XX:GCLogFileSize=< file size >[ unit ]
-Xloggc:/path/to/gc.log
UseGCLogFileRotation은 로그 파일 롤링 정책을 명시한다. log4j
, s4lj
등과 같이 말이다. NumberOfGCLogFiles는 단일 어플리케이션 라이프사이클에서 로그파일이 최대 몇개까지 쓰여질 수 있는지를 나타낸다. GCLogFileSize는 로그 파일의 최대 크기를 명시한다. loggc는 로그 파일의 위치를 명시한다.
눈여겨볼 점은, 2개의 JVM 파라미터가 더 있다는 건데, (XX:+PrintGCTimeStamps와 -XX:PrintGCDateStamps) 가비지콜렉션 로깅에서 날짜 형식에 맞는 타임스탬프를 출력할 때 유용하다.
이를테면, 최대 100개의 가비지 콜렉션 로그 파일을 할당하고 싶고, 각 파일은 50MB 사이즈를 최대 크기로 가지며, '/home/user/log/'
위치에 저장하고 싶다면, 아래와 같은 설정을 해줄 수 있다.
-XX:+UseGCLogFileRotation
-XX:NumberOfGCLogFiles=10
-XX:GCLogFileSize=50M
-Xloggc:/home/user/log/gc.log
하지만, 문제는 하나의 추가적인 데몬 스레드가 항상 모니터링 시스템을 위해 백그라운드에 돌아가고 있다는 것이다. 이 행위가 오히려 퍼포먼스 보틀넥을 만들 수도 있다; 그래서 프로덕션 레벨에서는 파라미터 가지고 잘 놀지 않는다.
규모가 큰 앱에서는 out of memory error를 만나기 쉽다. 일명 OOM(Out Of Memory)에러는 결국 앱을 중단시킨다. 이러한 에러는 매우 크리티컬하며, 문제를 재현해서 트러블슈팅하기 매우 어렵다.
JVM에서는 아래와 같은 파라미터를 제공하여, 힙 메모리를 물리적인 파일로 덤프할 수 있다. 이 파일은 나중에 메모리 유출을 찾는데 기여할 수 있다.
-XX:+HeapDumpOnOutOfMemoryError
-XX:HeapDumpPath=./java_pid<pid>.hprof
-XX:OnOutOfMemoryError="< cmd args >;< cmd args >"
-XX:+UseGCOverheadLimit
OutOfMemory
에러가 났을 때 물리적인 파일로 힙을 덤프하라는 뜻이다.<pid>
태그를 이름에서 찾는다면, OutOfMemory
에러를 일으킨 현재 프로세스의 프로세스 id가 .hprof
포맷과 함께 파일 이름에 추가될 것이다.OutOfMemory
에러가 발생했을 때, 실행될 긴급 명령어를 적어놓을 수 있다. 적절한 명령어를 "< cmd args>"
자리에 넣으면 된다. 이를테면, 만일 OutOfMemory
직후에 서버를 재시작하고 싶다면, 다음과 같이 설정하면 된다.-XX:OnOutOfMemoryError="shutdown -r"
OutOfMemory
에러가 던져지기 이전에 GC에서 소비되는 가상머신의 시간의 영역을 제한하는 정책이다.OS 환경에서는 32비트와 64비트 패키지가 설치된다. JVM은 자동으로 32비트 환경 패키지를 선택한다.
수동으로 64비트를 선택하고 싶다면, 아래와 같은 파라미터를 이용하면 된다.
-d<OS bit>
<OS bit>
은 32 또는 64가 될 수 있다. 더 많은 정보는 여기에서 확인해볼 수 있다.
char[]
배열로 복사함으로써 힙메모리를 최적화한다.GB/MB/KB
에서 인자를 받는다. 더 큰 페이지 사이즈를 설정함으로써, 가상 메모리 하드웨어 리소스의 사용을 더 좋게 만들 수 있다; 하지만, PermGen을 위한 더 큰 공간 사이즈를 일으킬 수 있다. 결과적으로 힙 공간의 사이즈를 강제로 줄일 수도 있다.shirinking
을 피하기 위해 가비지 컬렉션 이후에 최대 퍼센티지의 힙 여유 사이즈를 설정한다.expansion
을 피하기 위해 가비지 컬렉션 이후에 최소 퍼센티지의 힙 여유 사이즈를 설정한다. 힙의 사용량을 모니터링하기 위해 JDK에서 제공하는 VisualVM을 사용할 수 있다.byte[]
타입을 사용한다. 이 결과로 문자열을 순수한 ASCII 포맷으로 표현이 가능하다.일반적인 어플리케이션 퍼포먼스를 증대시키기 위해 사용될 수 있는 JVM 파라미터들에 대해 알아보았다. 몇몇가지는 디버깅 목적으로 사용될 수 있다.
여기에서 더 많은 파라미터들을 자세히 알아볼 수 있다.