자바 메모리 분배 와 회수 전략 깊이 이해

서론
자바 기술 시스템 에서 언급 한 메모리 자동화 관 리 는 결국 메모리 의 배분 과 회수 두 가지 문제 입 니 다.이전에 자바 회수 에 관 한 지식 을 여러분 과 이 야 기 했 습 니 다.오늘 은 자바 대상 의 메모리 배분 에 대해 이야기 하 겠 습 니 다.쉽게 말 하면 대상 의 메모리 분 배 는 쌓 여 있 는 분배 입 니 다.대상 은 주로 신세대 Eden 에 분 배 됩 니 다.(대상 이 메모리 에 있 는 분 대 는 쓰레기 회수 에 보충 되 고 알 고 싶 은 것 도 참고 할 수 있 습 니 다.)로 컬 스 레 드 분배 버퍼 를 시작 하면 스 레 드 에 따라 TLAB 에 우선 분 배 됩 니 다.소수의 경우 에 도 옛 시대 에 직접 분배 된다.
2.전형 적 인 배분 전략
1.대상 은 Eden 에서 우선 배정
일반적으로 대상 은 Eden 에 우선 배정 되 는데 Eden 이 충분 한 공간 이 없 을 때 jvm 은 Minor GC 를 발기 합 니 다.만약 아직도 충분 한 공간 분배 가 없다 면,뒤에 또 다른 조치 가 있 으 니,아래 에서 언급 할 것 이다.
가상 컴퓨터 의 짝 짓 기 로그 인자-XX:+PrintGCdetails 를 설정 합 니 다.쓰레기 를 회수 할 때 메모리 의 회수 로 그 를 인쇄 하고 프로 세 스 가 종 료 될 때 현재 메모리 영역 별 할당 상황 을 출력 합 니 다.다음은 구체 적 인 예 를 살 펴 보 자.먼저 jvm 의 매개 변수 인 Xms20m-Xmx20m-Xmn10m 를 설정 해 야 한다.이 세 가지 매개 변 수 는 자바 더미 의 크기 가 20m 이 고 확장 할 수 없다 는 것 을 설명 한다.그 중에서 10m 는 신세대 에 게 분배 되 고 나머지 10m 는 옛날 에 분배 된다.XX:SurvivorRatio=8 은 jvm 의 기본 신세대 중 Eden 과 Survivor 비율 이 고 기본 값 은 8:1 입 니 다.그 이 유 는 신세대 대상 의 98%가 다음 GC 에서 회수 되 기 때문에 복제 알고리즘 을 사용 하여 쓰레기 를 회수 하기에 적합 하기 때문에 신세대 10M 의 메모리 중 8M 는 Eden 이 고 1M 은 Survivor 이 며 다른 1M 은 복제 알고리즘 을 사용 하지 않 은 메모리 블록 이자 Survivor 이다.

public class ReflectTest {

  private static final int _1MB = 1024*1024;
  
  public static void testAllocation(){
    byte[] allocation1 , allocation2 , allocation3 , allocation4;
    allocation1 = new byte[2 * _1MB];
    allocation2 = new byte[2 * _1MB];
    allocation3 = new byte[2 * _1MB];
    allocation4 = new byte[6 * _1MB];
  }
  
  public static void main(String[] args) {
    ReflectTest.testAllocation();
  }
  
}
출력 은 다음 과 같 습 니 다.

Heap
 PSYoungGen   total 9216K, used 6651K [0x000000000b520000, 0x000000000bf20000, 0x000000000bf20000)
 eden space 8192K, 81% used [0x000000000b520000,0x000000000bb9ef28,0x000000000bd20000)
 from space 1024K, 0% used [0x000000000be20000,0x000000000be20000,0x000000000bf20000)
 to  space 1024K, 0% used [0x000000000bd20000,0x000000000bd20000,0x000000000be20000)
 PSOldGen    total 10240K, used 6144K [0x000000000ab20000, 0x000000000b520000, 0x000000000b520000)
 object space 10240K, 60% used [0x000000000ab20000,0x000000000b120018,0x000000000b520000)
 PSPermGen    total 21248K, used 2973K [0x0000000005720000, 0x0000000006be0000, 0x000000000ab20000)
 object space 21248K, 13% used [0x0000000005720000,0x0000000005a07498,0x0000000006be0000)
eden 이 81%를 차지 한 것 은 allocation 1,allocation 2,allocation 3 이 모두 신세대 Eden 에 분배 되 었 다 는 것 을 알 수 있다.
2.대상 은 옛날 에 직접 분배
큰 대상 은 긴 문자열 과 배열 과 유사 한 연속 메모리 공간 이 필요 한 대상 을 말한다.큰 대상 은 가상 컴퓨터 의 메모리 분포 에 있어 좋 은 일이 아니다.한 바퀴 만 살아 남 는 큰 대상 jvm 을 많이 만나면 더욱 처리 하기 어렵 고 코드 를 쓸 때 이런 문 제 를 피해 야 한다.가상 컴퓨터 에서-XX:Pretenure SizeThreshold 인 자 를 제 공 했 고 이 값 보다 큰 대상 은 옛날 에 직접 분 배 했 습 니 다.이렇게 하 는 목적 은 Eden 구역 과 Survivor 구역 사이 에 대량의 메모리 copy 가 발생 하지 않도록 하기 위해 서 입 니 다.앞에서 말 한 쓰레기 회수 알고리즘 복사 알고리즘 을 언급 한 적 이 있 으 면 더 이상 말 하지 않 겠 습 니 다.

public class ReflectTestBig {

  private static final int _1MB = 1024*1024;
  
  public static void testAllocation(){
    byte[] allocation2 , allocation3 , allocation4;
    allocation2 = new byte[2 * _1MB];
    allocation3 = new byte[2 * _1MB];
    allocation4 = new byte[6 * _1MB];
  }
  
  public static void main(String[] args) {
    ReflectTestBig.testAllocation();
  }
  
}
출력 은 다음 과 같 습 니 다.

Heap
 PSYoungGen   total 8960K, used 4597K [0x000000000b510000, 0x000000000bf10000, 0x000000000bf10000)
 eden space 7680K, 59% used [0x000000000b510000,0x000000000b98d458,0x000000000bc90000)
 from space 1280K, 0% used [0x000000000bdd0000,0x000000000bdd0000,0x000000000bf10000)
 to  space 1280K, 0% used [0x000000000bc90000,0x000000000bc90000,0x000000000bdd0000)
 PSOldGen    total 10240K, used 6144K [0x000000000ab10000, 0x000000000b510000, 0x000000000b510000)
 object space 10240K, 60% used [0x000000000ab10000,0x000000000b110018,0x000000000b510000)
 PSPermGen    total 21248K, used 2973K [0x0000000005710000, 0x0000000006bd0000, 0x000000000ab10000)
 object space 21248K, 13% used [0x0000000005710000,0x00000000059f7460,0x0000000006bd0000)
allocation 4 가 설 치 된-XX:Pretenure SizeThreshold=3145728 을 넘 어 섰 음 을 알 수 있 습 니 다.임의의 allocation 4 는 옛날 시대 에 직접 배정 되 었 고 옛날 시대 의 점용 율 은 60%입 니 다.여기 설정-XX:Pretenure SizeThreshold=3145728 은-XX:Pretenure SizeThreshold=3m 로 쓸 수 없습니다.그렇지 않 으 면 jvm 에서 식별 할 수 없습니다.
3.장기 생존 의 대상 은 노년기 에 접어 들 것 이다.
가상 컴퓨터 는 테이프 수집 사상 으로 메모 리 를 관리 하 는 이상 메모리 회 수 는 어떤 대상 이 신세대 에 두 어야 하고 어떤 대상 이 옛날 에 두 어야 하 는 지 식별 해 야 한다.목적 을 달성 하기 위해 jvm 은 모든 대상 에 게 연령 카운터(Age)를 정의 했다.대상 이 Eden 에서 태 어 나 첫 번 째 Minor GC 를 넘 긴 후에 도 살아 남 고 Survivor 에 보관 할 수 있다 면 Survivor 로 이동 해 대상 의 나 이 를 1 로 설정 합 니 다.대상 자 는 마 이 너 GC 를 한 번 피 할 때마다 나 이 를 1 로 늘 리 고,그의 나이 가 1 년 한도 값 을 넘 으 면 해당 대상 자 는 노년기 로 올라간다.이 한도 값 jvm 은 기본적으로 15 이 며,-XX:MaxTenuringThreshold 를 통 해 설정 할 수 있 습 니 다.

public class JavaTest { 
 
  static int m = 1024 * 1024; 
 
  public static void main(String[] args) { 
    byte[] a1 = new byte[1 * m / 4]; 

     byte[] a2 = new byte[7 * m]; 

     byte[] a3 = new byte[3 * m]; //GC 
  } 
}
출력 은 다음 과 같 습 니 다.

[GC [DefNew: 7767K->403K(9216K), 0.0062209 secs] 7767K->7571K(19456K), 0.0062482 secs]  
[Times: user=0.00 sys=0.00, real=0.01 secs]  
a3 ok 
Heap 
 def new generation  total 9216K, used 3639K [0x331d0000, 0x33bd0000, 0x33bd0000) 
 eden space 8192K, 39% used [0x331d0000, 0x334f9040, 0x339d0000) 
 from space 1024K, 39% used [0x33ad0000, 0x33b34de8, 0x33bd0000) 
 to  space 1024K,  0% used [0x339d0000, 0x339d0000, 0x33ad0000) 
 tenured generation  total 10240K, used 7168K [0x33bd0000, 0x345d0000, 0x345d0000) 
  the space 10240K, 70% used [0x33bd0000, 0x342d0010, 0x342d0200, 0x345d0000) 
 compacting perm gen total 12288K, used 381K [0x345d0000, 0x351d0000, 0x385d0000) 
  the space 12288K,  3% used [0x345d0000, 0x3462f548, 0x3462f600, 0x351d0000) 
  ro space 10240K, 55% used [0x385d0000, 0x38b51140, 0x38b51200, 0x38fd0000) 
  rw space 12288K, 55% used [0x38fd0000, 0x396744c8, 0x39674600, 0x39bd0000)
a2 가 한 번 살아 남 았 고 나 이 는 1 로 설 치 된-XX:MaxTenuring Threshold=1 을 만족 시 켰 기 때문에 a2 는 옛날 에 들 어 갔 고 a3 는 신세대 에 들 어 갔다.
4.동적 대상 연령 판정
서로 다른 프로그램의 메모리 상태 에 더욱 잘 적응 하기 위해 가상 컴퓨터 는 항상 대상 의 연령 이-XX:MaxTenuring Threshold 가 설정 한 값 이 옛날 로 올 라 갈 수 있 도록 요구 하지 않 습 니 다.만약 에 Survivor 공간 에서 같은 연령 의 모든 대상 크기 의 합 이 Survivor 공간의 절반 보다 크 고 연령 이 해당 연령 의 대상 보다 크 거나 같 으 면 노년 층 에 직접 들 어 갈 수 있 습 니 다.-XX:MaxTenuringThreshold 의 설정 값 에 도달 할 필요 가 없습니다.
5.공간 분배 담보
마 이 너 GC 가 발생 했 을 때 가상 기 회 는 노후 로 승진 할 때마다 평균 크기 가 노후 의 남 은 공간 보다 큰 지 를 측정 하고,그 이상 이면 FUll GC 를 한 번 직접 진행한다.작 으 면 HandlerPromotionFailyre 설정 의 보증 허용 여 부 를 확인 하 는 데 실 패 했 으 며,허용 된다 면 Minor GC 만 진행 하고,허용 되 지 않 는 다 면 FUll GC 도 한 번 개선 해 야 합 니 다.신세대 에덴 이 대상 을 바 꿀 수 없 을 때 이 대상 을 옛날 에 맡 긴 다 는 것 이다.
3.자주 사용 하 는 jvm 매개 변수 설정
1.-Xms:초기 더미 크기,기본 값(MinHeapFreeRatio 매개 변 수 는 조정 가능)의 남 은 메모리 가 40%보다 적 을 때 JVM 은-Xmx 의 최대 제한 까지 더 커진다.
2.Xmx:최대 더미 크기,기본 값(MaxHeapFreeRatio 매개 변 수 는 조정 가능)의 남 은 메모리 가 70%이상 일 때 JVM 은-Xms 까지 쌓 는 최소 제한 을 줄 일 수 있 습 니 다.
3.-Xmn:젊 은 세대 크기(1.4or lator),이곳 의 크기 는(eden+2 survivor space)입 니 다.jmap-heap 에 표 시 된 New gen 과 다 릅 니 다.
전체 더미 크기=젊 은 세대 크기+연로 대 크기+지구 대 크기.
젊 은 세 대 를 늘 리 면 나이 든 세대 의 크기 를 줄 일 수 있 습 니 다.이 수 치 는 시스템 성능 에 큰 영향 을 미 칩 니 다.Sun 은 전체 더미 의 3/8 로 설정 하 는 것 을 추천 합 니 다.
4.-XX:NewSize:젊 은 세대 크기 설정(for 1.3/1.4).
5.-XX:MaxNewSize:젊 은 세대 최대 치(for 1.3/1.4).
6.-XX:PermSize:지구 대(perm gen)의 초기 값 을 설정 합 니 다.
7.-XX:MaxPermSize:지구 대 최대 치 를 설정 합 니 다.
8.-Xss:각 스 레 드 의 스 택 크기,JDK 5.0 이후 각 스 레 드 스 택 크기 는 1M 입 니 다.이전 에는 각 스 레 드 스 택 크기 가 256 K 였 습 니 다.더욱 응용 가능 한 스 레 드 에 필요 한 메모리 크기 를 조정 합 니 다.같은 물리 적 메모리 에서 이 값 을 줄 이면 더 많은 스 레 드 를 생 성 할 수 있 습 니 다.그러나 운영 체 제 는 한 프로 세 스 의 스 레 드 수 에 제한 이 있어 서 무한 생 성 할 수 없습니다.경험 치 는 3000~5000 정도 입 니 다.
9.-XX:NewRatio:젊 은 세대(Eden 과 두 개의 Survivor 구역 포함)와 늙 은 세대 의 비율(지구 대 제외),-XX:NewRatio=4 는 젊 은 세대 와 늙 은 세대 가 차지 하 는 비율 이 1:4 이 고 젊 은 세대 가 전체 스 택 의 1/5 를 차지한다 고 밝 혔 다.Xms=Xmx 와 Xmn 을 설정 한 경우 이 인 자 는 설정 할 필요 가 없습니다.
10.-XX:Survivor Ratio:Eden 구역 과 Survivor 구역 의 크기 비례 는 8 로 설정 하면 두 개의 Survivor 구역 과 한 Eden 구역 의 비례 는 2:8 이 고 한 개의 Survivor 구역 은 전체 젊 은 세대 의 1/10 을 차지한다.
11.-XX:LargePageSizeInBytes:메모리 페이지 의 크기 를 너무 크게 설정 하면 Perm 의 크기 에 영향 을 줄 수 있 습 니 다.
12,-XX:+DisableExplicitGC:System.gc()닫 기
13.-XX:MaxTenuring Threshold:쓰레기 의 최대 연령,0 으로 설정 하면 젊 은 세대 의 대상 은 Survivor 구역 을 거치 지 않 고 바로 늙 은 세대 에 들 어 갑 니 다.늙 은 세대 에 대한 응용 은 효율 을 높 일 수 있 습 니 다.이 값 을 큰 값 으로 설정 하면 젊 은 세대 의 이미지 가 Survivor 구역 에서 여러 번 복 제 됩 니 다.그러면 대상 이 젊 은 세대 의 생존 시간 을 증가 시 킬 수 있 습 니 다.젊 은 세대 에서 회수 되 는 확률 을 증가 시 킵 니 다.이 매개 변 수 는 GC 직렬 일 때 만 유효 합 니 다.
14.-XX:Pretenure SizeThreshold:대상 이 몇 개가 넘 으 면 구 생 대 에 직접 분배 되 고 단위 바이트 의 신 생 대 는 Parallel Scavenge GC 를 사용 할 때 무효 하 며 다른 하 나 는 구 생 대 에 직접 분배 되 는 경우 가 큰 배열 대상 이 며 배열 에 외부 인용 대상 이 없습니다.
15.-XX:TLABWasteTarget Percent:TLAB 는 eden 구역 의 백분율 을 차지한다.
보충
Minor GC 와 FUll GC 의 차이 점:
신세대 GC(Minor GC):신세대 에서 발생 하 는 쓰레기 수집 동작 을 말한다.자바 대상 의 대수 가 1 차 GC 를 벗 어 나 지 못 하기 때문에 Minor GC 는 사용 이 빈번 하고 일반 회수 속도 도 빠르다.
옛날 GC(FULL GC/Major GC):옛날 에 발생 한 GC 를 말 하 는데 Major GC 가 나 타 났 다.적어도 한 번 은 마 이 너 GC(그러나 절대적 이지 않 고 Parallel Scavenge 수집 기의 수집 전략 에서 Major GC 를 직접 진행 하 는 선택 과정 이 있다).Major GC 의 속 도 는 일반적으로 Minor GC 보다 10 배 이상 느리다.
이상 의 이 편 은 자바 메모리 배분 과 회수 전략 을 깊이 이해 하 는 것 이 바로 편집장 이 여러분 에 게 공유 하 는 모든 내용 입 니 다.여러분 에 게 참고 가 되 고 여러분 들 이 저 희 를 많이 지지 해 주시 기 바 랍 니 다.

좋은 웹페이지 즐겨찾기