JVM Metaspace 메모리 넘 침 문제 해결 방안

현상
얼마 전에 회사 온라인 환경의 자바 응용 프로그램 은 OOM 의 이상 경보 로 인해 전체 서비스 가 클 러 스 터 에서 끌 어 낼 수 없 었 습 니 다.로 컬 모 의 재현 현상 은 다음 과 같 습 니 다.

당시 의 해결 방안 은 metaspace 의 용량 을 증가 시 키 는 것 이 었 다.-XX:MaxMetaspace Size=500 m 는 원래 의 기본 256 m 에서 500 m 로 바 뀌 었 다.oom 이 다시 나타 나 지 않 았 지만 이것 은 임시 해결 방안 일 뿐 회사 의 모니터링 시스템 을 통 해 metaspace 의 사용 상황 이 증가 하고 있 는 것 을 관찰 한 다음 에 업무 방 문 량 이 점점 커지 면서 한도 값 에 도달 할 수 있 었 다.

분석
Metascace 메타 공간 은 주로 저장 류 의 메타 데이터 정보 입 니 다.우리 의 응용 에 불 러 온 각종 설명 정보,예 를 들 어 클래스 이름,속성,방법,방문 제한 등 은 일정한 구조 에 따라 Metascace 에 저 장 됩 니 다.
이 를 통 해 알 수 있 듯 이 metaspace 공간 증 가 는 반사 류 로 딩,동적 에이전트 가 생 성 한 클래스 로 딩 등 으로 인 한 것 이다.즉,Metaspace 의 크기 는 로 딩 류 의 데이터 와 관계 가 있 고 로 딩 류 가 많 을 수록 metaspace 가 사용 하 는 메모리 도 커진다.
그 당시 의 업무 장면 을 알 고 있 는 이 유 는 메 일 서비스 가 주문 상세 인터페이스 에 접근 하 는 방 문 량 이 갑자기 증가 하고 log 의 eroor 로 그 를 보 니 대부분 주문 상세 인터페이스 에서 먼저 보 고 된 이 문제 가 있 었 기 때 문 입 니 다.java.lang.OutOf Memory Error:Metaspace

여기 서 저 는 테스트 환경 자바 응용 jvm 에-XX:+TraceClass Loading-XX:+TraceClass Unloading 에서 다음 과 같은 로 딩 과 마 운 트 해제 상황 을 기록 한 다음 에 jmeter 여러 스 레 드 를 통 해 주문 상세 한 인 터 페 이 스 를 호출 하여 metaspace 가 넘 치 는 현상 을 모 의 한 결과 catalina.out 파일 에서 지 는 것 은 업무 에 사용 되 는 클래스 를 제외 하고 대량의 반사 류 가 있 음 을 발 견 했 습 니 다.다음 과 같 습 니 다.

이러한 반사 류 가 빈번하게 로드 되 고 마 운 트 해제 되 는 것 은 정상 적 이지 않다.Arthas 진단 도 구 를 통 해 호출 체인 을 관찰 한 결과 매번 호출 인터페이스 가 반사 적 인 방식 으로 이 루어 진 것 을 발견 했다.

현재 우리 의 프로젝트 는 모두 SOA 프레임 워 크 를 바탕 으로 대외 적 으로 방문 을 제공 하고 있 으 며,위의 그림 sun.reflect 호출 자 에서 도 알 수 있 습 니 다.

위의 그림 을 통 해 알 수 있 듯 이 바 텀 인 터 페 이 스 를 호출 할 때 모두 반사 적 인 방식 으로 클래스 의 인 스 턴 스 를 얻 고 프레임 바 텀 코드 를 보면 확인 할 수 있다.

마찬가지 로 바 텀 인터페이스 에서 돌아 오 는 제 이 슨 데이터 의 역 직렬 화 에 도 반사 가 사용 된다.


코드 를 계속 따라 가면 반 사 된 실현 을 볼 수 있 습 니 다.자바.lang.Class 의 ReflectionData 대상 을 사용 합 니 다.

ReflectionData 는 내부 정적 클래스 가 캐 시 되 어 있 습 니 다.그 안의 속성 은 우리 가 반사 작업 을 할 때 사용 해 야 할 속성 Field,방법 Method 와 구조 함수 등 입 니 다.그러나 문제 가 있 습 니 다.reflection Data 는 SoftReference 소프트 에 의 해 인용 되 어 수식 되 었 습 니 다.다음 과 같 습 니 다.

부 드 러 운 인용 이 라면 메모리 공간 이 부족 할 때 회수 할 수 있 습 니 다.회수 하면 다음 에 사용 하면 반사 로 만 다시 가 져 올 수 있 습 니 다.
한편,SoftReference 가 회수 되 었 는 지 여 부 는 SoftRefLRUPolicy MSPerMB 매개 변수 값 과 관계 가 있 습 니 다.온라인 JVM 의 설정 을 살 펴 보면 XX:SoftRefLRUPolicy MSPerMB 라 는 매개 변 수 는 0 으로 설정 되 어 있 습 니 다.

SoftRefLRUPolicy MSPerMB 라 는 매개 변 수 는 1M 의 빈 공간 마다 유지 할 수 있 는 SoftReference 대상 의 생존 시간(단 위 는 ms 밀리초)을 의미 하 며,LRU 는 Least Recently Used 의 줄 임 말로 최근 가장 적 게 사용 되 고 있다.
이 값 jvm 은 기본적으로 1000 ms 입 니 다.0 으로 설정 되면 소프트 인용 대상 이 바로 회수 되 고 새로운 종 류 를 자주 생 성하 여 재 활용 효 과 를 얻 지 못 할 수 있 습 니 다.
위의 그림 에서 대량의 sun.reflect.Generated Serialization Constructor Accessor,Generated MethodAccessor 가 이렇게 생 겼 다.
나 는 이 매개 변 수 를 기본 값-XX:SoftRefLRUPolicy MSPerMB=1000(1 초)으로 바 꾸 었 고 생산 환경 검증 하에 발표 한 후에 내 려 왔 으 며 지금까지 기본적으로 안정 되 었 다.

조정 후 기본적으로 다시 파동 이 나타 나 지 않 았 다.
총화
  • 현 재 는 주로 JVM 의-XX:SoftRefLRUPolicy MSPerMB 값 을 수정 하여 metaspace 상승 문 제 를 해결 하고 추 후 변 화 를 지속 적 으로 관찰 하여 파 라 메 터 를 적당 하 게 조정 할 것 이다.이 인자 가 왜 0 으로 설정 되 었 는 지 에 대해 서 는 ops 를 찾 아 확인 해 야 합 니 다
  • 우리 의 응용 은 대량의 RPC 상호작용 이 필요 하 다.I/O 집약 형 업무 에 속 하고 SOA 를 사용 하면 Dubbo 는 비슷 한 문 제 를 만 날 수 있다.위의 소스 코드 분석 을 통 해 이것 은 피 할 수 없 는 것 임 을 알 수 있다.(하나의 직렬 화 협의,예 를 들 어 hessian 을 제외 하고방법 반 사 를 하지 않 는 방식 으로 값 을 부여 합 니 다)자체 적 으로 사용 하 는 Spring 프레임 워 크 를 포함 하여 많은 부분 이 반 사 를 통 해 이 루어 집 니 다.예 를 들 어 AOP,그리고 우리 가 자주 사용 하 는 JsonUtils 도구 도 있 습 니 다.Dump 파일 을 통 해 대량의 속성 복사 와 반사 작업 이 존재 하 는 것 을 알 수 있 습 니 다
  • 그래서 우 리 는 평소에 업무 코드 개발 에서 두 대상 의 할당 작업 을 만나면 반사 적 인 방식 으로 이 루어 지지 않도록 한다.예 를 들 어 아래 의 코드:

    여기 서 하 는 대상 복사 작업 은 apache common-beanutils.jar 의 BeanUtils 를 사용 합 니 다.이런 바 텀 은 javabeans+반사 로 실현 되 고 성능 이 떨 어 지 며 메모리 비용 이 비교적 많 습 니 다.시스템 이 높 고 병행 하 는 상황 에서 Metaspace 공간 이 너무 빨리 증가 하기 쉬 우 므 로 이렇게 사용 하 는 것 을 권장 하지 않 습 니 다.
    필드 가 적 으 면 직접 값 을 부여 하면 됩 니 다.많 으 면 Cglib 의 BeanCopier 류 를 사용 할 수 있 습 니 다.BeanCopier 류 의 바 텀 은 asm 바이트 코드 조작 방식 으로 대상 복사 작업 을 할 수 있 고 성능 손실 과 메모리 비용 이 비교적 적 습 니 다.
    또는 MapStruct 라 는 set,get 방법 을 만 드 는 도 구 를 사용 하면 효과 가 좋 습 니 다.
    이상 이 바로 본 고의 모든 내용 입 니 다.여러분 의 학습 에 도움 이 되 고 저 희 를 많이 응원 해 주 셨 으 면 좋 겠 습 니 다.

    좋은 웹페이지 즐겨찾기