jvm 튜닝의 메모리 누수 분석

  I. 소개

      심각한 메모리 누수가 메모리 오버플로를 일으키고 메모리 오버플로가 결국 프로그램 충돌로 이어진다는 것을 우리 모두 알고 있습니다. 며칠 전, 내분비 장애로 인해 거의이 문제가 발생했습니다. 매일 밤 WeChat이나 전화가 와서 프로젝트가 중단되었다고 말할 까봐 걱정해야했습니다. 헤이, 말을 너무 많이하면 눈물 이니까 주제로 바로 가자.

2. 문제 설명

1. 배포 환경

      리눅스

2. 문제 발견

        프로젝트가 처음 시작되었을 때 응답 속도가 느린 문제가있었습니다. 심지어 직접 502도 문제였습니다. 내 마음에 가장 먼저 떠오르는 것은 데이터베이스의 문제이며, 온라인 데이터베이스에 연결된 시스템에 mysql 클라이언트를 설치했습니다 (연결 명령 : mysql -h (ip) -u (사용자 이름) -p ( 암호) ), 하나의 Zhang 테이블을 선택하면 쿼리 효율성에 문제가 없습니다. 이제 잘못된 것은 없습니다. 로그를 확인합시다. 모두 깨진 파이프 예외 (클라이언트가 요청을 보냈고 서버가 오랜 시간 동안 응답하지 않음) 인 것으로 나타 났으며 자세히 살펴보면이 예외는 거의 java.lang.OutOfMemoryError가 생성 된 후 나타났습니다. 신속하게 top 명령을 켜고 상황도 예상되며 CPU가 90 % 이상으로 치솟았습니다.

     상단:

       f 또는 F 현재 디스플레이에서 항목을 추가하거나 삭제합니다.

  o 또는 O를 눌러 표시된 항목의 순서를 변경합니다.

  l 스위치 디스플레이 평균 부하 및 시작 시간 정보.

  m 메모리 정보 표시로 전환합니다.

  t 디스플레이 프로세스 및 CPU 상태 정보로 전환합니다.

  c 명령 이름과 전체 명령 줄을 표시하도록 전환합니다.

  M은 상주 메모리의 크기에 따라 정렬됩니다.

  P는 CPU 사용량의 백분율에 따라 정렬됩니다.

  T는 시간 / 누적 시간별로 정렬됩니다.

  3. 메모리 누수 분석 프로세스

      어떤 스레드가 CPU를 차지하고 있는지 확인하는 top 명령에 따르면 CPU의 사용률이 높게 유지되었습니다.

   (1) jps, ps 또는 기타 방법을 통해 java의 프로세스 ID PID를 찾습니다.

   (2) top -p <pid> H (현재 프로세스의 모든 스레드)를 눌러 cpu가 100 %를 차지하는 스레드 번호를 찾으십시오. 발견 된 스레드 번호는 2 진이고 16 진수로 변환해야하기 때문입니다.

8 개의 높은 CPU 스레드가 gc 가비지 수집을 수행하는 것으로 확인되었습니다.

   (3) jstack -l <pid> | grep <변환 된 16 진수>를 사용하여 스레드가 수행하는 작업을 확인합니다. 스레드의 덤프에는 RUNNABLE (실행 중), BLOCKED (차단됨) 및 WAITING (대기 중)의 세 가지 상태가 있습니다. 결과가 "Concurrent Mark-Sweep GC Thread"prio = 10 tid = 0x0000000053293800 nid = 0x *** runnable과 비슷하다는 것을 발견하면 jvm이 스레드를 표시하고 지운다는 의미이므로 jvm은 바쁜 가비지 수집입니다. jvm은 객체의 수명주기에 따라 메모리를 여러 영역으로 나누기 때문입니다. 젊은 세대와 구세대로 나뉘며, 젊은 세대의 대부분의 객체는 작은 객체입니다 .JVM은 자주 재활용됩니다. 남은 객체는 복제 알고리즘 에 따라 from 영역에서 to 영역 으로 전송됩니다 . 살아남은 개체의 복사 비용 중 적은 금액 만 지불하면 수집이 완료됩니다. 구세대의 물체의 생존율은 상대적으로 높고 그것에 압력을 할당 할 여분의 공간이 없기 때문에 재활용을 위해 " mark-and-sort "알고리즘이 사용됩니다.

(4) jmap -heap <pid>를 사용하여 힙 메모리 상황을 확인하고 이전 영역의 메모리가 99 %까지 늘어난 것을 확인합니다. 프로그램이 느리게 응답하거나 직접 멈춘 이유를 이해하는 것은 어렵지 않습니다. 쓰레기 수거로 바쁘다 시간이 없다

(5) 메모리 오버플로는 시스템에서 할당 한 메모리가 부족하여 발생할 수도 있으므로 8g의 메모리 (xmx8g)를 할당 한 결과 프로그램이 시작된 지 얼마되지 않아 CPU가 90 % 이상 실행되는 것을 발견했습니다. 나는 이것이 전혀 문제가 아니라는 것을 깨달았고 쓰레기가 수집되지 않고 더 많은 메모리가 소비된다는 것을 깨달았으므로 코드를 최적화하기 시작했습니다.

(6) 코드 최적화? 어디서부터 시작합니까? 회수되지 않은 개체와 가장 많은 공간을 차지하는 개체를 찾아야합니다. 그래서 서버에서 힙 파일을 덤프하고 분석했습니다 ( command : jmap -dump : live, format = b, file = head.xx <pid> ).이 파일은 약간 수 있습니다. 압축하는 것이 가장 좋습니다 (명령 : tar -czf dump.tar.gz dump.xx ). 삭제하지 않으면 jhat 명령을 사용하여 자세히 분석 할 수도 있습니다. (참고 : 이것을 사용하는 경우 기기에 충분한 메모리가 있는지 확인해야합니다. 그렇지 않으면 기기가 멈출 수 있습니다.)

(7) 파일을 삭제 한 후 특별한 메모리 분석 도구가 필요합니다. 그중 사용할 수있는 두 가지 도구가 있는데, 하나는 jdk1.6 이상에서 제공되는 도구 인 jvisualvm입니다.하지만이 도구는 5G 힙 파일을 분석하기가 매우 어렵고 대기 시간이 상대적으로 길며 결과는 다음과 같습니다. 직관적이지 않습니다. 따라서 두 번째 유형 인 eclipse의 플러그인 메모리 분석기 (다운로드 : http://www.eclipse.org/downloads/download.php?file=/mat/1.8.1/rcp/MemoryAnalyzer-1.8.1.20180910) 를 사용하는 것이 좋습니다 . -win32. win32.x86_64.zip ). 열린 힙 파일이 매우 큰 경우 MAT의 시작 매개 변수 (memoryanalyzer.ini의 xmx 매개 변수)를 수정해야합니다.

(8) 개봉 후 사용자 테이블에있는 오브젝트의 상당 부분이 재활용되지 않는 것으로 확인되어 사용자 테이블의 많은 필드가 쓸모 없지만 제거되지 않은 것으로 생각했습니다. 다른 장소에서 사용하고 있습니까? 재활용되지 않는 개체이므로 불필요한 필드를 모두 제거하고 업데이트하십시오. 잠시 후 그는 다시 죽었고 그의 심장은 무너지기 직전이었다. . .

(9) jmap -histo <pid>를 사용하여 푸시의 메모리 사용량을 확인합니다.이 명령을 사용하여 사용자 테이블의 개체가 여전히 많은 메모리를 차지하고 있는지 확인하고 찾습니다. 문제가 해결되지 않았습니다.

(10) 그래서 방법은 없습니다, 혼자서 테스트를 작성하십시오. 재활용하지 않습니까? 사용자 클래스에서 가비지 콜렉션의 finalize () 메소드를 덮어 쓰고 JPA의 save 메소드를 호출 한 후이 클래스가 재활용되지 않은 것을 발견했습니다. 주의 깊은 연구에 따르면이 클래스는 최대 절전 모드 캐싱 기술을 사용하며 캐싱에 의해 발생한다는 것을 발견했습니다 ( 캐싱은 수행 된 작업의 결과를 빠르게 찾는 데 사용되는 데이터 구조이므로 작업에 더 많은 리소스가 필요한 경우 여러 번 사용될 것입니다. 일반적으로 사용되는 입력 데이터의 작업 결과를 캐시하여 다음에 작업이 호출 될 때 캐시 된 데이터가 사용되도록하는 것이 일반적입니다. 캐시는 일반적으로 동적 방식으로 구현됩니다. 캐시 설정이 올바르지 않으면 캐시 된 데이터가 사용됩니다. lot 캐시를 사용하면 메모리 오버플로의 결과가 발생하므로 사용되는 메모리 용량과 데이터 검색 속도의 균형을 맞출 필요가 있습니다. 그래서 캐시를 제거하고 다시 테스트 한 결과 객체가 마침내 복구되었음을 알았습니다.

3. 요약

      나중에 신중하게 생각 해보니 10 만명 이상의 사용자가 있고 더 많은 사람들이 온라인 상태 였는데 캐싱으로 인해 사용자 개체가 재활용되지 않고 쌓여서 메모리 오버플로가 발생했습니다.

     문제가 해결 될 것이라고 생각했지만 다음날 프로젝트가 다시 중단되고 심장이 다시 중단되었다고 들었습니다. 재빨리 기기를 켜고 상위 정보를 살펴본 결과 CPU가 정상인 것을 확인한 후 대역폭을 살펴 보았는데 대역폭이 부족하다는 것이 밝혀졌습니다.

     

 

추천

출처blog.csdn.net/weixin_39886135/article/details/83791601