>Java >java지도 시간 >Java 예외 OutOfMemoryError에 대한 솔루션

Java 예외 OutOfMemoryError에 대한 솔루션

不言
不言앞으로
2019-01-30 11:08:173212검색

이 기사는 Java 예외 OutOfMemoryError에 대한 해결책을 제공합니다. 특정 참조 값이 있으므로 도움이 필요할 수 있습니다.

Java 가상 머신 사양 설명에서 프로그램 카운터 외에도 가상 머신 메모리의 다른 여러 실행 영역에서 OOM 예외가 발생할 수 있습니다. 여기서는 코드를 사용하여 각 런타임 영역에 무엇이 저장되어 있는지 확인하고 이를 처리하는 방법에 대해 논의합니다.

Java 힙 오버플로

Java 힙은 객체 인스턴스를 저장하는 데 사용됩니다. 객체가 지속적으로 생성되고 GC 루트와 객체 사이에 도달 가능한 경로가 있어 이러한 객체를 지우는 가비지 수집 메커니즘을 방지할 수 있습니다. 최대 힙에 도달하면 용량 제한 이후 메모리 오버플로 예외가 발생합니다.

예외 재현

코드는 다음 가상 머신 매개변수를 사용합니다.

-Xms20m -Xmx20m -XX:+HeapDumpOnOutOfMemoryError

이러한 방식으로 Java 힙의 크기는 20MB로 제한되며 확장할 수 없습니다. 가상 머신은 -XX:+HeapDumpOnOutOfMemoryError 매개변수를 통해 메모리 오버플로 예외가 발생할 때 분석을 위해 현재 메모리 힙 덤프 스냅샷을 덤프할 수 있습니다.

다음 코드를 사용하여 확인하세요.

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

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

실행 결과:

java.lang.OutOfMemoryError: Java heap space
Dumping heap to java_pid3460.hprof ...
Heap dump file created [28199779 bytes in 0.237 secs]

Solution

Java 힙 메모리 OOM 예외는 실제 애플리케이션에서 흔히 발생하는 메모리 오버플로 예외입니다. 공간" ".

이 분야의 이상 현상을 해결하기 위한 일반적인 방법은 먼저 MAT와 같은 메모리 이미지 분석 도구를 사용하여 메모리 누수 또는 메모리 오버플로가 있는지 확인하는 것입니다.

메모리 누수인 경우 추가로 도구를 사용하여 누수된 객체에서 GC Roots까지의 참조 체인을 확인하여 누수된 객체가 GC Roots와 어떻게 연관되어 있는지 알아보고 가비지 수집기가 차지한 공간을 자동으로 회수하지 못하도록 방지할 수 있습니다. .

메모리 누수가 아닌 경우, 즉 메모리에 있는 개체가 실제로 살아남아야 하는 경우에는 가상 머신의 힙 매개변수를 확인하고 머신의 물리적 메모리와 비교하여 가능 여부를 확인해야 합니다. 증가하다. 코드 수준에서 수명주기가 너무 길고 상태가 너무 오랫동안 유지되는 객체가 있는 경우 프로그램 실행 중에 메모리 소비를 줄이도록 노력하십시오.

가상 머신 스택과 로컬 메소드 스택 오버플로

HotSpot 가상 머신에서는 가상 머신 스택과 로컬 메소드 스택의 구분이 없기 때문에 HotSpot의 경우 -Xoss 매개변수가 존재하더라도 실제로는 스택 용량만 유효합니다. -Xss 매개변수로 설정됩니다.

예외 재현

단일 스레드에서 코드는 다음 가상 머신 매개 ​​변수를 사용합니다.

-Xss128k

이 매개 변수를 사용하여 스택 용량을 줄이고 다음 코드를 사용하여 예외를 재현합니다.

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;
        }
    }
}

Solution

가상 머신 기본 매개변수, 대부분의 경우 스택 깊이(각 방법으로 스택에 푸시된 프레임 크기가 동일하지 않기 때문에 대부분의 경우라고만 말할 수 있음)는 1000~2000에 도달하므로 전혀 문제가 없습니다. , 일반 메소드 호출(재귀 포함)의 경우 이 깊이이면 충분합니다.

그러나 너무 많은 스레드 생성으로 인해 메모리 오버플로가 발생하는 경우 스레드 수를 줄일 수 없거나 64비트 가상 머신을 교체할 수 없는 경우 유일한 옵션은 대신 최대 힙 및 스택 용량을 줄이는 것입니다. 더 많은 스레드를 보려면.

기본 직접 메모리 오버플로

DirectMemory 용량은 -XX: MaxDirectMemorySize를 통해 지정할 수 있습니다. 지정하지 않으면 기본값은 Java의 최대 힙과 동일합니다.

예외 재현

다음 가상 머신 매개변수를 사용하세요.

-Xmx20M -XX:MaxDirectMemorySize=10M

예외를 재현하려면 다음 코드를 사용하세요.

public class DirectMemoryOOM {
    private static final int _1MB = 1024 * 1024;
    public static void main(String[] args) throws Exception {
        Field unsafeField = Unsafe.class.getDeclaredFields()[0];
        unsafeField.setAccessible(true);
        Unsafe unsafe = (Unsafe) unsafeField.get(null);
        while (true) {
            unsafe.allocateMemory(_1MB);//直接申请分配内存
        }
    }
}

Solution

DirectMemory로 인한 메모리 오버플로의 분명한 특징은 힙에 표시되지 않는다는 것입니다. 덤프 파일 예외.

OOM 이후의 덤프 파일이 매우 작고 프로그램에서 NIO가 직간접적으로 사용되는 경우 이것이 이유인지 확인하는 것이 좋습니다.

위 내용은 Java 예외 OutOfMemoryError에 대한 솔루션의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
이 기사는 cnblogs.com에서 복제됩니다. 침해가 있는 경우 admin@php.cn으로 문의하시기 바랍니다. 삭제
이전 기사:J2EE란?다음 기사:J2EE란?