JVM: 41개의 글
JMX를 이용해서 자바 어플리케이션의 상태를 모니터링 한다. 모니터링 하던 중 CPU가 갑자기 튀는 현상이 발생했다. 그래서 원인을 찾아야 하는데.. 어떻게할까? 1. top 으로 java가 CPU를 많이차지하는지 확인 - 대부분의 경우 java겠지만, 혹시나 다른 프로세스가 CPU를 차지하고있지는 않은지 확인한다. java가 아닌 다른 프로세스가 CPU를 많이차지하고 있으면 그 프로세스가 원인이므로 쉽게 끝날 수 있다. 하지만 java가 원인이라면... 어떤 스레드가 차지하는지 분석이 필요하다. 2. java가 많이 차지한다면, top 에서 H(대문자)를 입력해서 스레드 단위로 CPU점유율 확인 $ top - 터미널에서 top을 입력하면 현재 동작중인 스레드와 CPU, Memory 점유율을 확인할 수 ..
최적의 성능을 내기 위해서는 모든 자바 프로세스가 차지하고 있는 공간의 총합이 머신의 물리 메모리보다 작아야 한다. -Xms512m -Xmx2048m 실제로 어플리케이션이 처음 시작할 때는 512M를 사용하지만, 2048M를 시스템에 예약한다. 시스템에 예약할때 과도하게 할 경우? 성능상의 이슈는 되지 않음 -XX:MaxDirectMemorySize=N 네이티브 메모리 버퍼의 최대 크기를 지정한다 JNI를 이용해서 네이티브 메모리에 버퍼를 직접할당해서 사용할 수 있음 이러한 기능이 있는 이유는, 소켓 프로그래밍을 예로 들 수 있다. allocateDirect()를 이용해서 네이티브 메모리에 버퍼를 직접 할당하지 않고, 자바 버퍼를 사용할 경우 소켓을 이용해서 다른 머신과 통신할 경우 소켓은 자바 버퍼와 ..
객체 재사용 객체를 생성하는데 비용이 큰 객체들은 일반적인 객체 생명 주기를 따르지 않고, 한번만 생성되고 재사용해야 한다. 재사용 하면 무조건 좋기만 할까? 객체를 무분별하게 재사용하면 안 좋은 이유 재사용 객체는 오래 사용되기 때문에 올드 제너레이션에서 공간을 차지할 것이다. Full GC 를 수행하는데 걸리는 시간은 살아있는 객체 수에 비례한다. 1GB의 올드 제너레이션에서 많은 객체가 살아남았을 때보다 3GB의 올드 제너레이션에서 적은 객체가 살아남았을 때 GC시간이 더 빠르다. 따라서 객체를 재사용하게 되면 올드 제너레이션에 살아남은 객체가 많아져서 GC시간이 늘어난다. 더욱이, G1을 사용하게 되면 동시 병렬 컬렉터들의 성능도 살아있는 객체 수에 비례한다. Full GC가 발생하지 않더라도 살..
힙 메모리를 관리하는데 있어, 힙 크기를 늘리는 것과 비슷한 효과를 받을 수 있는 것이 메모리를 적게 사용하는 것이다. 기본적인 개념을 먼저 알아보고, 문자열을 많이 사용하는 어플리케이션의 경우 String을 사용할 때 어떠한 것을 조심해야하는지 살펴보자 객체 크기 줄이기 인스턴스 변수 개수 줄이기, 변수의 크기 줄이기 Ex. double -> float 객체의 크기는 항상 8byte 배수이다. 객체에서 실제로 사용하는 변수의 크기가 9byte이거나10byte이거나 모두 18byte크기의 객체로 잡히고, 나머지는 빈 값으로 채워진다. 때문에 변수의 크기나 개수를 줄인다고 이점이 있을수도 있고 없을 수도 있지만 시도하지 않을 이유는 없다. 시간 vs 공간 인스턴스 변수를 무조건 줄인다고 좋을까? 계산의 중..
주의! 컬렉션과 메모리누수 List, Map, Set 같은 자바 컬렉션 클래스들을 사용할 때는 항상 주의해야한다! 컬렉션 클래스 안에 담겨있는 인스턴스는 프로그램에서 사용되든,안되든 모두 사용되는 것으로 판단되어 GC의 대상이 되지 않아 메모리 누수의 흔한 원인이 된다. carMap에 담긴 car1,car2,car3 인스턴스들은 사용자에 의해 사용되지 않음에도 불구하고 JVM은 그것을 아직은.. 잡아내지 못한다. 때문에 그대로 놔두면 메모리누수가 발생한다. 컬렉션에서 인스턴스를 비워내야만 그때서야 car 인스턴스가 가비지 컬렉터에의해 소거된다. 위 프로그램을 돌리고 힙 히스토그램을 확인한 결과, 아래와 같이 jcmd를 이용해서 GC 후의 결과를 살펴보았음에도, Car 인스턴스 3개가 소거되지 않고 남아있..
큰 객체 할당, TLAB 요약 TLAB( Thread Local Allocation Buffer ) 보다 큰 객체들은 TLAB 바깥에 할당되서 TLAB 안에 할당되는 객체보다 처리가 느리다. TLAB 은 스레드 내의 로컬 영역으로, TLAB 안에 할당된 객체는 스레드 동기화 등의 추가적인 처리를 하지 않고 로컬 변수처럼 처리할 수 있기 때문에 더 빠르다. TLAB 은 에덴내의 한 영역으로 에덴의 크기에 좌우된다. TLAB 을 튜닝하려면 JFR을 사용해서 TLAB 밖에 할당되는 객체들의 크기를 확인한 뒤, TLAB이 최대한 많은 객체들을 포함할 수 있도록 TLAB의 크기를 늘리면 된다. 주의할 점은 JFR의 TLAB 확인 기능은 어플리케이션에 많은 부하가 발생해서 기본적으로 꺼져있으며 프러뎍선 환경에서 사..
크다? JVM의 TLAB 크기에 좌우 TLAB 이란? TLAB : Thread Local Allocation Buffer , 스레드 로컬 할당 버퍼 - 에덴 내에 있는 한 영역 - 스레드 마다 할당되는 객체 버퍼 - 하나의 스레드가 처리할 수 있는 객체의 최대 크기 - 각 스레드마다 스레드 로컬에 할당되므로, 동기화에 신경쓰지 않아도 된다. - TLAB에 할당되지 못하는 크기가 큰 객체들은 TLAB 밖에 할당된다. - TLAB 밖에 할당된 객체들은 스레드 동기화등 여러가지 절차가 추가적으로 필요하기 때문에 처리하는데 TLAB 안에 있는 객체보다 처리가 느리다. TLAB이 가득차면, 일정 크기의 객체는 더이상 TLAB안에 할당될 수 없다. 이 시점에서 JVM에게는 두 가지 선택사항이 있다. 1) TLAB ..
JMC, JFR 을 이용해서 메모리 누수를 진단해보자! Memory Leak 발견하기 메모리 누수로 인한 잦은 GC로 어플리케이션이 느려질 수 있으며, 결국 OutOfMemoryError가 발생한다. 메모리 누수를 JFR을 이용해서 찾을 수 있다. Old Generation에 GC가 발생했는데도 꾸준히 살아있는 객체들의 갯수가 증가한다면 메모리 누수를 의심할 수 있다. 메모리 누수는 오랜 기간 쌓인 로그를 봐야할 경우가 많기 때문에 JMC을 이용해서 로그를 잘 남겨놔야 한다. ( JMC Event Trigger를 이용해서 특정시간마다 특정기간동안 JFR 을 돌려서 기록할 수 있다) Memory Leak 클래스 찾기 메모리 누수가 발견되었다면, 어떤 클래스에서 메모리 누수가 발생하는지 찾아야한다. 메모리 ..
(프로덕션 환경에서 사용할려면 라이센스 필요, 그외에는 무료로 사용 가능) JMC 는 두 가지 주요 목적으로 사용될 수 있다 1) JVM의 상태를 모니터링 2) Java Flight Recorder를 이용해서 생성한 덤프 파일 분석 JMC, JFR을 통해 무엇을 할 수 있는지 살펴보자 ※ 주의! 어플리케이션 성능 JFR을 이용해서 어플리케이션을 모니터링할 때는 성능을 주의해야한다. JFR을 이용해서 얻을 수 있는 데이터 종류가 많기 때문에, 모든 것을 측정하려고 하면 어플리케이션에 부하가 심해진다. 따라서 원하는 데이터만 골라서 기록해야 한다. JFR은 데이터의 종류 뿐만 아니라 데이터를 얼마나 자주 측정할지 등 기본적인 설정이 필요하다. JFR은 미리 설정된 프로파일을 제공한다. (default.jfc..
1. 서바이버 스페이스 이해하기 Young Generation에서 객체들의 이동은 다음과 같다. 2. 서바이버 스페이스의 존재 이유 - 몇번의 Minor GC 동안 영 제너레이션 내에 객체가 남아있도록 설계하여, 올드 제너레이션으로 승격될 만큼 오래 살아남지 못한 객체들은 그 전에 제거한다. - S0S1을 핑퐁을 쳐가며 오래 살아남지 못할 객체들은 Old Generation 전에 소거한다. 3. 서바이버 스페이스 오버플로우 서바이버 스페이스가 작아서 또는 어떤 이유로 꽉차게 되면 Minor GC발생 시, 객체가 에덴에서 올드 제너레이션으로 바로 승격된다. 오랫동안 사용되지 않을 객체라도 서바이버의 필터링을 거치지 못하기 때문에 올드 제너레이션으로 이동하게 되어 Full GC를 초래한다. 서바이버 스페이스..