JVM 런타임 데이터 영역

5.1 기본 방법

스레드 시작 클래스 작성

package cn.guardwhy.jvm_02;

public class ThreadDemo {
    
    
    public static void main(String[] args) {
    
    
        new Thread(()->{
    
    

        }, "Curry").start();
    }
}

시작 방법의 소스 코드보기

public synchronized void start() {
    
    
    /**
     * This method is not invoked for the main method thread or "system"
     * group threads created/set up by the VM. Any new functionality added
     * to this method in the future may have to also be added to the VM.
     *
     * A zero status value corresponds to state "NEW".
     */
    if (threadStatus != 0)
        throw new IllegalThreadStateException();

    /* Notify the group that this thread is about to be started
     * so that it can be added to the group's list of threads
     * and the group's unstarted count can be decremented.
     */
    group.add(this);

    boolean started = false;
    try {
    
    
        // 调用了一个start0方法
        start0();
        started = true;
    } finally {
    
    
        try {
    
    
            if (!started) {
    
    
                group.threadStartFailed(this);
            }
        } catch (Throwable ignore) {
    
    
            /* do nothing. If start0 threw a Throwable then
                  it will be passed up the call stack 
             */
        }
    }
}

private native void start0();

네이티브 메서드 요약

native 키워드가있는 것은 모두 Java 범위에 도달 할 수 없음을 나타내므로 기본 C 언어 라이브러리를 호출하십시오.! 네이티브 메서드 스택 (Native Method Stack)을 입력하고 네이티브 메서드의 네이티브 인터페이스를 호출합니다.JNI (Java Native Method Interface). JNI의 특정 역할은 Java 사용을 확장하고 Java를위한 다양한 프로그래밍 언어를 통합하는 것입니다.

C / C ++가 만연했을 때 Java가 탄생했을 때 발판을 마련하려면 C와 C ++를 호출하는 프로그램이 있어야합니다.따라서 네이티브로 표시된 코드를 처리하기 위해 메모리에 특수 영역이 열리고, 그 구체적인 방법은 네이티브 메서드 스택에 네이티브 메서드를 등록하고 (ExecutionEngine) 실행 엔진 실행시 네이티브 라이브러리를로드하는 것입니다.

5.2 프로그램 카운터

프로그램 카운터 : 프로그램 카운터 레지스터

각 스레드에는 스레드 전용 인 프로그램 카운터가 있습니다. 이것은 메서드 영역에서 메서드 바이트 코드를 가리키는 포인터입니다 (명령어를 가리키는 주소, 즉 실행될 명령 코드를 저장하는 데 사용됨). , 실행 엔진에서 다음 명령어를 읽는 것은 매우 작은 메모리 공간입니다. 거의 무시할 수 있습니다.

5.3 분석법 영역

메소드 영역은 모든 스레드에서 공유됩니다. 모든 필드와 메서드 바이트 코드는 물론 생성자, 인터페이스 코드와 같은 일부 특수 메서드도 여기에 정의됩니다. 간단히 말해서 정의 된 모든 분석법 정보가 공유 공간 인이 영역에 저장됩니다. 힙과 같은 스레드간에 공유됩니다.

JDK7 이전 (영구 생성)

클래스 정보, 상수, 문자열 상수, 클래스 정적 변수 및 가상 머신에 의해로드 된 Just-In-Time 컴파일러에 의해 컴파일 된 코드와 같은 데이터를 저장하는 데 사용됩니다. 클래스가 처음로드 될 때마다 해당 메타 데이터는 영구 생성에 배치됩니다. 영구 생성의 크기에는 제한이 있으며, 너무 많은 클래스가로드되면 영구 생성 메모리 오버 플로우 (즉, java.lang.OutOfMemoryError : PermGen)가 발생할 수 있습니다.

JDK8 이후

JDK8은 HotSpot JVM에서 영구 생성을 완전히 제거하고 원래 데이터를 Java Heap 또는 Native Heap (Metaspace)로 마이그레이션합니다. 대신 메타 스페이스라는 또 다른 메모리 영역이 있습니다.

메타 스페이스

Metaspace는 HotSpot JVM에서 메소드 영역의 실현입니다.메서드 영역은 주로 클래스 정보, 상수 풀, 메서드 데이터, 메서드 코드, 기호 참조 등을 저장하는 데 사용되지만 인스턴스 변수는 힙 메모리에 저장되며 메서드 영역과는 관련이 없습니다.메타 스페이스의 특성은 영구 생성과 유사합니다.모두 JVM 사양의 메소드 영역 구현입니다.메타 공간과 영구 생성의 가장 큰 차이점은 메타 공간이 가상 머신에 있지 않고 로컬 메모리를 사용한다는 것입니다..
메모리 크기는 -XX : MetaspaceSize 및 -XX : MaxMetaspaceSize를 통해 구성 할 수 있습니다.

Metaspace가 차지하는 공간이 설정된 최대 값에 도달하면 GC가 트리거되어 데드 오브젝트 및 클래스 로더를 수집합니다.

코드 예

package cn.guardwhy.jvm_02;

public class Test {
    
    
    // 定义常量
    private int age;
    private String name = "guardwhy";
    public static void main(String[] args) {
    
    
        Test st = new Test();
        st.age = 10;
        st.name = "Curry";
    }
}

메모리 분석

5.4 스택

스택 및 대기열

스택 : 후입 선출 / 선입 선출

대기열 : FIFO

스택 기능

스택 관리 프로그램은 8 가지 기본 유형, 객체 참조 및 인스턴스를 저장하는 메소드를 실행 합니다.스택의 장점은 액세스 속도가 힙보다 빠르고 레지스터에 이어 두 번째이며 스택 데이터를 공유 할 수 있다는 것입니다.

생각 : 왜 main ()이 먼저 실행되고 마지막으로 끝날까요?

스택의 특성에 따라 결정됩니다.

1. 스택은 스택 메모리라고도하며 Java 프로그램의 실행을 담당하며 스레드가 생성 될 때 생성되고 수명이 스레드의 수명을 따르며 스레드가 종료되면 스택 메모리가 해제됩니다.
2.스택의 경우 가비지 콜렉션 문제가 없으며 스레드가 종료되는 한 스택이 종료됩니다. 라이프 사이클은 스레드 전용 인 스레드의 라이프 사이클과 동일합니다..
3. 메서드가 자체적으로 조정되면 스택 오버플로 (재귀 루프 테스트)가 발생합니다.

스택 작동 방식

"선입 선출"/ "선입 선출"원칙을 따릅니다.

Java 스택의 구성 요소 인 스택 프레임입니다.스택 프레임은 가상 머신이 메소드 호출 및 메소드 실행을 실행하는 데 사용되는 데이터 구조입니다.. 스택 프레임은 스레드와 독립적이며 각 스레드에는 자체 스택 프레임이 있습니다. 메서드의 로컬 변수 테이블, 동적 링크 정보, 메서드 반환 주소 및 피연산자 스택 정보를 캡슐화합니다. 호출 시작부터 실행 완료까지의 첫 번째 방법은 가상 머신 스택의 스택에서 스택으로의 스택 프레임 프로세스에 해당합니다.

스택 + 힙 + 메서드 영역 간의 상호 작용

HotSpot은 포인터를 사용하여 개체에 액세스합니다.액세스 클래스 메타 데이터의 주소는 Java 힙에 저장됩니다.. 참조는 객체의 주소를 저장합니다.

5.5 힙

jdk1.7 이전

힙 힙 이후에는 JVM 메모리 힙의 인스턴스가 하나만 있으며 힙 메모리 크기를 조정할 수 있으며 클래스 로더
는 클래스, 메서드, 종종 변수를 힙 메모리에 가져와 모든 참조 유형을 저장 하는 필요한 클래스 파일을 읽습니다 . 실행기의 실행을 용이하게하기 위해 힙 메모리는
세 부분 으로 나뉩니다 .

  • 젊은 세대 스페이스 Young / New
  • 임기 생성 공간 Old / Tenure
  • 영구 공간 파마

힙 메모리는 논리적으로 새, 이전, 영구 (메타 공간 : JDK8 이후의 이름)의 세 부분으로 나뉩니다.

코드 예

package cn.guardwhy.jvm_02;

import java.util.Random;
/*
* OutOfMemoryError 
*/
public class Hello {
    
    
    public static void main(String[] args) {
    
    
        // 定义字符串变量
        String str = "guardwhy Learn English";
        while (true){
    
    
            str += str + new Random().nextInt(666666666) + new Random().nextInt(777777777);
        }
    }
}

의 결과

GC 가비지 수집은 주로 신생아 지역과 노인 지역 에 있으며 가벼운 GC와 무거운 GC로 구분됩니다. 메모리가 충분하지 않거나 무한 루프가있는 경우java.lang.OutOfMemoryError : Java 힙 공간

신생아 영역

신생아 영역은 클래스가 태어나고, 성장하고, 죽는 영역으로, 가비지 수집기가 클래스를 생성, 적용, 수집하여 수명을 다합니다.. 신생아 영역은 Eden Space와 Survivor Space의 두 부분으로 나뉩니다.모든 클래스는 에덴 지역의 새로운 것입니다, 살아남은 영역은 영역 0과 영역 1입니다. Garden of Eden의 공간이 다 사용되면 프로그램은 객체를 다시 생성해야하며 JVM의 가비지 수집기는 가비지 수집 (Minor GC)을 수행합니다. 에덴 동산. Garden of Eden의 나머지 개체를 생존 구역 0으로 이동합니다. 생존 구역 0도 가득 차면 구역을 다시 가비지 수집 한 다음 구역 1로 이동 한 다음 구역 1도 가득 차면 (여기서는 존 0 번 존과 존 1 번은 대체 과정) 이후 노인 케어 영역으로 이동합니다. 노인 케어 영역도 꽉 찬 경우, 이때 MajorGC (Full GC)가 생성되어 노인 케어의 기억을 정리합니다. 지역.노인 케어 영역에서 Full GC를 실행하고 개체를 여전히 저장할 수없는 경우 OOM 예외 "OutOfMemoryError"가 생성됩니다. java.lang.OutOfMemoryError : java 힙 공간이 비정상이면 Java 가상 머신의 힙 메모리가 충분하지 않음을 의미합니다.다음과 같은 이유로

  • JVM (Java Virtual Machine)의 힙 메모리 설정이 충분하지 않으며 매개 변수 -Xms (초기 값 크기) 및 -Xmx (최대 크기)로 조정할 수 있습니다.
  • 많은 수의 큰 개체가 코드에 생성되고 오랫동안 가비지 수집기에서 수집 할 수 없거나 (참조 됨) 무한 루프가 발생합니다.

HotSpot 메모리 관리

참고 : 개체마다 수명주기가 다릅니다. Java의 개체 중 98 %가 임시 개체입니다.

영구 영역 (Perm)

영구 저장 영역 (Perm)은 JDK 자체에서 전달하는 클래스 및 인터페이스의 메타 데이터를 저장하는 데 사용되는 영구 메모리 영역입니다. 즉, 운영 환경에 필요한 클래스 정보와로드 된 데이터를 저장합니다. 이 영역은 가비지 수집기에 의해 재활용되지 않습니다.이 영역이 차지하는 메모리는 JVM이 닫힐 때만 해제됩니다..
java.lang.OutOfMemoryError : PermGen 공간이 나타나면 Java 가상 머신에 영구 생성 Perm을위한 메모리 설정이 충분하지 않음을 의미합니다. 일반적으로 이러한 상황은 프로그램이 시작될 때 많은 타사 jar 패키지를로드해야하고 Tomcat이 너무 많은 응용 프로그램을 배포했기 때문에 발생합니다. 또는 동적으로 생성 된 많은 클래스가 지속적으로로드되어 결국 Perm 영역이 가득 차게되어 OOM이 발생합니다.
참고 :

  • Jdk1.6 이전 : 영구 생성이 있으며 상수 풀 1.6이 메소드 영역에 있습니다.
  • Jdk1.7 : 영구적 인 생성이 있지만 점차 "영구적 인 생성"이되었으며 상수 풀이 힙에 있습니다.
  • Jdk1.8 이상 : 영구 생성이 없으며 상수 풀 1.8이 메타 공간에 있습니다.

3 구역 구조


힙과 마찬가지로 메소드 영역 (Method Area)은 각 스레드가 공유하는 메모리 영역으로 가상 머신로드를 저장하는 데 사용됩니다.: 클래스 정보 + 일반 상수 + 정적 상수 + 컴파일러 컴파일 된 코드, JVM 사양은 메소드 영역을 힙의 논리적 부분으로 설명하지만 Non-Heap (비힙)이라는 별칭도 가지고 있지만 목적은 To 더미에서 분리되어야합니다. HotSpot 가상 머신의 경우 메서드 영역을 "Parmanent Gen"이라고 부르는 것이 일반적이지만 엄밀히 말하면이 둘은 본질적으로 다르거 나 영구 생성을 사용하여 메서드 영역을 구현합니다.영구 생성은 메서드 영역 (인터페이스와 동일)의 구현입니다. Jdk1.7 버전에서는 원래 영구 생성에 배치 된 문자열 상수 풀이 제거되었습니다.. 상수 풀은 메소드 영역의 일부입니다. 클래스의 버전, 필드, 메소드 및 인터페이스 설명 정보 외에도 클래스 파일에는 상수 풀에 대한 정보도 있습니다. 컨텐츠의이 부분은 메소드 영역으로 들어갑니다. 클래스가로드 된 후 시정 수 풀이 저장됩니다.

추천

출처blog.csdn.net/hxy1625309592/article/details/114553604