>  기사  >  Java  >  JVM의 각 영역의 목적에 대한 자세한 설명과 잠재적인 예외에 대한 코드 예제

JVM의 각 영역의 목적에 대한 자세한 설명과 잠재적인 예외에 대한 코드 예제

黄舟
黄舟원래의
2017-03-20 10:56:191983검색

프로그램 카운터

는 바이트코드 해석기가 실행해야 하는 바이트코드 명령어를 선택하는 데 사용됩니다. 각 스레드에는 독립적인 프로그램 카운터가 있으며 스레드는 서로 영향을 미치지 않습니다. 스레드가 Java 메소드를 실행하는 경우 이 카운터는 네이티브 메소드를 실행하는 경우 실행 중인 가상 머신 바이트코드 명령의 메모리 주소를 기록합니다. 카운터가 정의되지 않았습니다. 이 영역은 JVM 사양에서 유일하게 OOM이 존재하지 않는 영역입니다.

가상 머신 스택(로컬 변수 공간)

컴파일러가 알고 있는 다양한 기본 데이터 유형(boolean, byte, char)이 저장됩니다. , short, int, float, long, double), 객체 적용(참조). 64비트 double 및 long은 2개의 슬롯을 차지합니다. 메모리 공간은 메소드를 입력할 때 할당해야 하는 로컬 변수 공간이 완전히 결정됩니다. -Xss

예외:

StackOverflowError 스택 깊이가 가상 머신에서 허용하는 깊이보다 큽니다.

OOM 가상 머신 스택을 동적으로 확장할 수 있는 경우(대부분의 Java 가상 머신은 동적으로 확장할 수 있지만 Java 가상 머신 사양에서는 고정 길이 가상 머신 스택), 확장이 충분한 메모리를 적용할 수 없는 경우

단일 스레드에서 스택 프레임이 너무 크거나 가상 머신 스택 용량이 너무 작은 경우, 메모리를 할당할 수 없는 경우 , 가상 머신은 모두 StackOverflowError

/**
* VM Args:-Xss128k
* 
* stack length:2402 Exception in thread "main" java.lang.StackOverflowError
*/
public class JavaVMStackSOF {

private int stackLength = 1;

public void stackLeak() {
    stackLength++;
    stackLeak();
}

public static void main(String[] args) throws Throwable {
    JavaVMStackSOF oom = new JavaVMStackSOF();
    try {
        oom.stackLeak();
    } catch (Throwable e) {
        System.out.println("stack length:" + oom.stackLength);
        throw e;
    }
}
}

를 발생시킵니다. 테스트가 단일 스레드에 국한되지 않는 경우 스레드를 지속적으로 설정하면 메모리 오버플로 예외가 발생할 수 있습니다. 그러나 이렇게 생성된 메모리 오버플로 예외는 점유 공간이 충분히 큰지 여부와는 관련이 없습니다. 정확하게 말하면, 이 경우 각 스레드의 스택에 할당된 메모리가 클수록 메모리 오버플로 예외가 발생하기 쉽습니다. .

운영 체제에서 각 프로세스에 할당하는 메모리는 제한되어 있기 때문에 예를 들어 32비트 창은 2GB로 제한됩니다. 이 테스트는 많은 수의 스레드를 생성하여 수행됩니다. 각 스레드는 스택 메모리를 점유하고 많은 양의 메모리를 할당하므로 시스템의 메모리가 부족해집니다. 자동으로 확장할 수 없도록

/**
 * VM Args:-Xss2M (这时候不妨设大些)
 *
 * java.lang.OutOfMemoryError:unable to create new native thread
 */
public class JavaVMStackOOM {

       private void dontStop() {
              while (true) {
              }
       }

       public void stackLeakByThread() {
              while (true) {
                     Thread thread = new Thread(new Runnable() {
                            @Override
                            public void run() {
                                   dontStop();
                            }
                     });
                     thread.start();
              }
       }

       public static void main(String[] args) throws Throwable {
              JavaVMStackOOM oom = new JavaVMStackOOM();
              oom.stackLeakByThread();
       }
}

로컬 메소드 스택

은 가상 머신 스택과 유사하지만 하나는 Java 메소드를 실행하는 가상 머신이고 다른 하나는 Native 메소드를 실행한다는 점만 다릅니다

예외 상황:

StackOverflowError 스택 깊이가 가상 머신에서 허용하는 깊이보다 큽니다

OOM

Java 힙

A 스레드가 공유하는 메모리 영역은 메모리 재활용의 관점에서 기본적으로 세대별 수집 알고리즘을 채택하므로 신세대와 구세대로 구분됩니다. 좀 더 세부적으로는 Eden 공간, From Survivor 공간, To Survivor 공간 등으로 나눌 수 있습니다. -Xmx -Xms 힙 공간 크기 제어

예외:

1.OOM 힙을 확장할 수 없는 경우

/**
 * VM Args:-Xms20m -Xmx20m -XX:+HeapDumpOnOutOfMemoryError
 * 
 * java.lang.OutOfMemoryError: Java heap space
 */
public class HeapOOM {

    static class OOMObject {
    }

    public static void main(String[] args) {
        List<OOMObject> list = new ArrayList<OOMObject>();

        while (true) {
            list.add(new OOMObject());
        }
    }
}

메서드 영역

스레드 간에 공유됩니다. 가상 머신에서 로딩한 클래스 정보, 상수, 정적 변수, 인스턴트 에디터로 컴파일한 코드 등의 데이터를 저장하는 것을 HotSpot 가상 머신의 불멸의 세대라 할 수 있습니다.

런타임 상수는 1.6 및 이전 버전에서 메서드 영역의 일부였습니다(String.intern()이 상수 풀을 동적으로 추가함) -XX:MaxPermSize는 크기를 제어합니다. JDK1.7 이상 버전에서는 Java 힙에서 메모리 조각이 열립니다.

예외 상황:

OOM

/**
* 需要在JDK1.6上才能复现,JDK1.7及之后版本的JVM已经将运行时常量池从方法区中移了出来,在Java 堆(Heap)中开辟了一块区域存放运行时常量池。
* 在JDK1.7上运行的效果则会一直执行,直到堆内存使用完毕
* VM Args:-XX:PermSize=10M -XX:MaxPermSize=10M 
*
* java.lang.OutOfMemoryError:PermGen space
*/
public class RuntimeConstantPoolOOM {

public static void main(String[] args) {
    // 使用List保持着常量池引用,避免Full GC回收常量池行为
    List<String> list = new ArrayList<String>();
    // 10MB的PermSize在integer范围内足够产生OOM了
    int i = 0;
    while (true) {
        list.add(String.valueOf(i++).intern());
    }
}
}
rrree

직접 메모리(가상 머신의 일부가 아님) 실행 시간 데이터 영역의 일부)

NIO는 Native 함수 라이브러리를 사용하여 외부 메모리를 직접 할당한 다음 이 메모리에 대한 참조로 Java 쌍에 저장된 DirectByteBuffer 개체를 통해 작동할 수 있습니다. 머신의 물리적 메모리에 의해 제한되며 -XX:MaxDirectMemorySize를 통해 지정할 수 있습니다. 지정하지 않을 경우 기본값은 Java 힙 최대값(-Xmx)과 동일합니다.

예외:

1 .OOM

아아아아

위 내용은 JVM의 각 영역의 목적에 대한 자세한 설명과 잠재적인 예외에 대한 코드 예제의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.