JVM 런타임 데이터 영역 힙 (힙 메모리)

런타임 데이터 영역 힙

힙의 핵심 개념

"Java Virtual Machine Specification"에서 Java 힙에 대한 설명은 다음과 같습니다. 모든 개체 인스턴스와 배열은 런타임에 힙에 할당되어야합니다. (힙은 모든 클래스 인스턴스 및 배열에 대한 메모리가 할당되는 런타임 데이터 영역입니다).

그러나 실용적인 관점에서 "거의"모든 개체 인스턴스는 여기에 메모리를 할당합니다. 스택에 여전히 일부 개체가 할당되어 있고 스택 프레임이 참조를 저장하기 때문에 배열과 개체가 스택에 저장되지 않을 수 있으므로이 참조는 힙에서 개체 또는 배열의 위치를 ​​가리 킵니다.

  • 힙은 JVM 프로세스에 고유합니다. 즉, 프로세스는 JVM 인스턴스에 해당하지만 프로세스는 여러 스레드를 포함하며 동일한 힙 공간을 공유합니다.
  • JVM 인스턴스에 대한 힙 메모리는 하나 뿐이며 힙은 Java 메모리 관리의 핵심 영역입니다.
  • Java 힙 영역은 JVM이 시작될 때 생성되고 크기가 결정되며 JVM에서 관리하는 가장 큰 메모리 공간입니다.
  • 그러나 힙 메모리의 크기는 조정할 수 있습니다.
  • "Java Virtual Machine Specification"은 힙이 물리적으로 불연속적인 메모리 공간에있을 수 있지만 논리적으로는 연속적인 것으로 간주되어야한다고 규정합니다 (운영 체제와 비교할 수 있음).
  • Java 힙은 스레드 전용 버퍼 (Thread Local Allocation Buffer, TLAB)로 나눌 수 있습니다. 즉, 힙의 모든 정보가 스레드에서 공유되는 것은 아닙니다.

다음 코드는 힙 메모리를 설명합니다.

public class HeapDemo {
    
    
    public static void main(String[] args) {
    
    
        System.out.println("start...");
        try {
    
    
            Thread.sleep(1000000);
        } catch (InterruptedException e) {
    
    
            e.printStackTrace();
        }

        System.out.println("end...");
    }
}

힙 크기를 설정하십시오.

-Xms10m : 최소 힙 메모리
-Xmx10m : 최대 힙 메모리
여기에 사진 설명 삽입

다음 그림은 Java VisualVM을 사용하여 VisualVM의 GC 플러그인을 통해 힙 공간의 내용을 보는 방법을 보여줍니다.
여기에 사진 설명 삽입

메서드가 종료 된 후에는 힙의 개체가 즉시 제거되지 않고 가비지 수집 중에 제거됩니다. 즉, GC가 트리거 될 때 수집됩니다.

힙의 개체가 즉시 회수되면 사용자 스레드가 영향을 받기 때문입니다.

힙, Java 스택 및 메소드 영역 간의 연결 :
여기에 사진 설명 삽입
힙 메모리 분석

Java 7 이전의 힙 메모리는 논리적으로 신생아 영역 + 노인 케어 영역 + 영구 영역의 세 부분으로 나뉩니다.

  • Young Generation Space Young / New는 Eden 영역과 Survivor 영역으로 나뉩니다.
  • 임기 생성 공간 Old / Tenure;
  • 영구 공간 파마.

Java 8 이상의 힙 메모리는 논리적으로 신생아 영역 연금 영역 + 메타 공간의 세 부분으로 나뉩니다.

  • Young / New in Young Generation Space는 Eden 영역과 Survivor 영역으로 나뉩니다.
  • 임기 생성 공간 Old / Tenure;
  • 메타 스페이스 메타.

컨벤션 : 신생아 영역-> 신세대-> 젊은 세대, 노인 케어 영역-> 노인 영역-> 구세대, 영구 영역-> 영구 세대
여기에 사진 설명 삽입
힙 공간 내부 구조 JDK1.8 이전에 영구 세대로 대체되었습니다. 메타 공간! ! !
여기에 사진 설명 삽입
힙 공간은 논리적으로 신생대, 구세대, 메타 스페이스를 포함하지만 실제로는 신생대와 구세대 만 포함합니다. 메타 스페이스는 메소드 영역이라고도합니다! ! !

힙 메모리 크기 및 OOM 설정

Java 힙 영역은 Java 개체 인스턴스를 저장하는 데 사용되므로 힙 크기는 JVM이 시작될 때 이미 설정되어 있으며 "-Xmx"및 "-Xms"옵션으로 설정할 수 있습니다.

  • "-Xms"는 힙 영역의 초기 메모리를 나타내는 데 사용되며 -xx : InitialHeapSize와 같습니다.
  • "-Xmx"는 힙 영역의 최대 메모리를 나타내는 데 사용되며 -XX : MaxHeapSize와 같습니다.
  • 힙 영역의 메모리 크기가 "-xmx"에 지정된 최대 메모리를 초과하면 outofMemoryError 예외가 발생합니다.
  • 일반적으로 두 개의 매개 변수 -Xms와 -Xmx는 동일한 값으로 구성됩니다. 목적은 Java 가비지 콜렉션 메커니즘이 힙 영역을 정리 한 후 힙 영역을 다시 계산하지 않고도 힙 영역의 크기를 계산할 수 있도록하는 것입니다. 따라서 성능이 향상됩니다.

기본적으로:

  1. 초기 메모리 크기 : 물리적 컴퓨터 메모리 크기 / 64;
  2. 최대 메모리 크기 : 실제 컴퓨터 메모리 크기 / 4.

다음 코드는 힙 메모리 크기를 확인하기 위해 테스트합니다.

public class HeapSpaceInitial {
    
    
    public static void main(String[] args) {
    
    

        //返回Java虚拟机中的堆内存总量
        long initialMemory = Runtime.getRuntime().totalMemory() / 1024 / 1024;
        //返回Java虚拟机试图使用的最大堆内存量
        long maxMemory = Runtime.getRuntime().maxMemory() / 1024 / 1024;

        System.out.println("-Xms : " + initialMemory + "M");
        System.out.println("-Xmx : " + maxMemory + "M");

        //System.out.println("系统内存大小为:" + initialMemory * 64.0 / 1024 + "G");
        //System.out.println("系统内存大小为:" + maxMemory * 4.0 / 1024 + "G");

        try {
    
    
            Thread.sleep(1000000);
        } catch (InterruptedException e) {
    
    
            e.printStackTrace();
        }
    }
}

출력 결과

-Xms : 246M
-Xmx : 3934M

힙 메모리의 메모리 할당을 보는 방법 :

jps  ->  jstat -gc 进程id

여기에 사진 설명 삽입
여기에 사진 설명 삽입
OutOfMemory 예

코드 예 :

public class OOMTest {
    
    
    public static void main(String[] args) {
    
    
        ArrayList<Picture> list = new ArrayList<>();
        while(true){
    
    
            try {
    
    
                Thread.sleep(20);
            } catch (InterruptedException e) {
    
    
                e.printStackTrace();
            }
            list.add(new Picture(new Random().nextInt(1024 * 1024)));
        }
    }
}

class Picture{
    
    
    private byte[] pixels;

    public Picture(int length) {
    
    
        this.pixels = new byte[length];
    }
}

시작 매개 변수 설정

-Xms500m -Xmx:500m
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
	at com.heu.heap.OOMTest.main(OOMTest.java:21)

VisualVM 도구를 통해 특정 메모리 사용량을 확인합니다.

여기에 사진 설명 삽입
Used heap이 500에 도달하면 OOM 예외가 발생 함을 알 수 있습니다.

남녀 노소

JVM에 저장된 Java 객체는 두 가지 범주로 나눌 수 있습니다.

  • 한 가지 유형은 수명주기가 짧은 순간 객체입니다. 이러한 유형의 객체는 생성되고 매우 빠르게 소멸됩니다. 수명주기가 짧으면 시간 내에 재활용 할 수 있습니다.
  • 다른 유형의 객체의 수명주기는 매우 길며 일부 극단적 인 경우에는 여전히 JVM의 수명주기와 일치 할 수 있습니다.

자바 힙 영역을 더 세분화하면 젊은 세대 (YoungGen)와 구세대 (oldGen)로 나눌 수 있습니다.

그중 젊은 세대는 에덴 공간, 생존자 0 공간, 생존자 1 공간 (때때로 지역에서 지역으로 불림)으로 나눌 수 있습니다.
여기에 사진 설명 삽입
다음 힙 매개 변수는 일반적으로 개발 중에 조정되지 않습니다.
여기에 사진 설명 삽입

  • 에덴 : From : to-> 8 : 1 : 1
  • 신세대 : 구세대-> 1 : 2

힙 구조에서 젊은 세대와 이전 세대의 비율을 구성하십시오.

  • 기본값 -XX : NewRatio = 2는 새로운 세대가 1을, 이전 세대가 2를, 새로운 세대가 전체 힙의 1/3을 차지함을 의미합니다.
  • -XX : NewRatio = 4를 수정할 수 있습니다. 이는 새로운 세대가 1을 차지하고 이전 세대가 4를 차지하며 새로운 세대가 전체 힙의 1/5을 차지함을 의미합니다.
  • 전체 프로젝트에서 수명주기가 긴 개체가 너무 많다는 것이 발견되면 튜닝을 위해 이전 세대의 크기를 조정할 수 있습니다.
  • HotSpot 가상 머신에서 Eden 공간과 나머지 두 생존자 공간의 기본 비율은 8 : 1 : 1입니다. 물론 개발자는 "-xx : SurvivorRatio"옵션을 통해이 공간 비율을 조정할 수 있습니다. 예 : -xx : SurvivorRatio = 8.

거의 모든 Java 객체는 Eden 영역에서 새롭고 대부분 (80 %) Java 객체는 새로운 세대에서 파괴됩니다 (일부 대형 객체는 Eden 영역에 저장할 수없는 경우 이전 세대로 직접 이동합니다).

"-Xmn"옵션을 사용하여 새 세대의 최대 메모리 크기를 설정할 수 있습니다.
그리고이 매개 변수는 일반적으로 기본값을 사용합니다.
여기에 사진 설명 삽입

추천

출처blog.csdn.net/qq_33626996/article/details/113888562