Java Heap OutOfMemoryError
Java 힙은 객체 인스턴스를 저장하는 데 사용되므로 계속 객체를 생성하고 GC 루트와 생성된 객체 사이에 도달 가능한 경로가 있는지 확인하여 객체 인스턴스가 가비지 컬렉팅 중이고 너무 많은 객체가 생성되면 힙 메모리가 부족해 OutOfMemoryError 예외가 발생하게 됩니다.
/** * @author xiongyongshun * VM Args: java -Xms10m -Xmx10m -XX:+HeapDumpOnOutOfMemoryError */ public class OutOfMemoryErrorTest { public static void main(String[] args) { List<Integer> list = new ArrayList<>(); int i = 0; while (true) { list.add(i++); } } }
위는 OutOfMemoryError 예외를 발생시키는 코드입니다. . 가비지 수집을 방지하기 위해 지속적으로 개체를 독립적으로 생성하고 목록에 저장하는 것을 볼 수 있습니다. 따라서 개체가 너무 많으면 힙 메모리가 오버플로됩니다.
java -Xms10m -Xmx10m -XX:+HeapDumpOnOutOfMemoryError를 사용하여 힙 메모리를 10MB로 설정하고 -XX:+HeapDumpOnOutOfMemoryError 매개 변수를 사용하여 OutOfMemoryError 예외가 발생할 때 JVM이 현재 메모리 스냅샷을 인쇄하도록 합니다. 이후의 편의를 위해 분석합니다.
위 코드를 컴파일하고 실행하면 다음과 같은 결과가 출력됩니다.
>>> java -Xms10m -Xmx10m -XX:+HeapDumpOnOutOfMemoryError com.test.OutOfMemoryErrorTest 16-10-02 23:35 java.lang.OutOfMemoryError: Java heap space Dumping heap to java_pid1810.hprof ... Heap dump file created [14212861 bytes in 0.125 secs] Exception in thread "main" java.lang.OutOfMemoryError: Java heap space at java.util.Arrays.copyOf(Arrays.java:3210) at java.util.Arrays.copyOf(Arrays.java:3181) at java.util.ArrayList.grow(ArrayList.java:261) at java.util.ArrayList.ensureExplicitCapacity(ArrayList.java:235) at java.util.ArrayList.ensureCapacityInternal(ArrayList.java:227) at java.util.ArrayList.add(ArrayList.java:458) at com.test.OutOfMemoryErrorTest.main(OutOfMemoryErrorTest.java:15)
Java stack StackOverflowError
우리는 알고 있습니다 JVM의 런타임 데이터 영역에는 가상 머신 스택이라는 메모리 영역이 있습니다. 이 영역의 역할은 각 메소드가 실행될 때 로컬 변수 테이블, 피연산자 스택을 저장하는 데 사용되는 스택 프레임을 생성하는 것입니다. 메소드 종료 및 기타 정보.
따라서 무한 재귀 호출을 생성할 수 있습니다. 재귀 깊이가 너무 크면 스택 공간이 소진되어 StackOverflowError 예외가 발생합니다. >구체적인 코드는 다음과 같습니다.
/** * @author xiongyongshun * VM Args: java -Xss64k */ public class OutOfMemoryErrorTest { public static void main(String[] args) { stackOutOfMemoryError(1); } public static void stackOutOfMemoryError(int depth) { depth++; stackOutOfMemoryError(depth); } }
위 코드를 컴파일하고 실행하면 다음과 같은 예외 메시지가 출력됩니다.
Exception in thread "main" java.lang.StackOverflowError at com.test.OutOfMemoryErrorTest.stackOutOfMemoryError(OutOfMemoryErrorTest.java:27)
메소드 영역 메모리 오버플로
, 因为 JDK8 已经移除了永久代, 取而代之的是 metaspace, 因此在 JDK8 中, 下面两个例子都不会导致 java.lang.OutOfMemoryError: PermGen space 异常.
런타임 상수 풀 오버플로
Java 1.6 및 이전 HotSpot JVM 버전에는 영구 생성 개념이 있습니다. 즉, GC의 세대별 수집 메커니즘을 메소드 영역으로 확장한 것입니다. 메소드 영역에서는 메모리의 일부를 상수 풀을 저장하는 데 사용하므로 코드에 상수가 너무 많으면 상수 풀 메모리가 사용됩니다. 소모되어 메모리 오버플로가 발생합니다. 그러면 상수 풀에 많은 수의 상수를 추가하는 방법은 String.intern() 메서드에 의존해야 한다는 것입니다. 이 String의 값이 이미 상수 풀에 있으면 이 메서드는 상수 풀에 있는 해당 문자열의 참조를 반환합니다. 그렇지 않으면 이 String에 포함된 값이 상수 풀에 추가되고 이 String 객체에 대한 참조를 반환합니다. JDK 1.6 이하 버전에서는 영구 생성에서 상수 풀이 할당되므로 "-XX:PermSize" 및 "-XX:MaxPermSize" 매개 변수를 설정하여 상수 풀의 크기를 간접적으로 제한할 수 있습니다.
, 上面所说的 String.intern() 方法和常量池的内存分布仅仅针对于 JDK 1.6 及之前的版本, 在 JDK 1.7 或以上的版本中, 由于去除了永久代的概念, 因此内存布局稍有不同.
다음은 상수 풀 메모리 오버플로를 구현하는 코드 예제입니다.
/** * @author xiongyongshun * VM Args: -XX:PermSize=10M -XX:MaxPermSize=10M */ public class RuntimeConstantPoolOOMTest { public static void main(String[] args) { List<String> list = new ArrayList<String>(); int i = 0; while (true) { list.add(String.valueOf(i++).intern()); } } }
이 예제에서는 String.intern( ) 메소드를 사용하여 상수 풀에 많은 수의 문자열 상수를 추가함으로써 상수 풀의 메모리 오버플로가 발생합니다.
JDK1.6을 통해 컴파일하고 컴파일합니다. 위의 코드를 실행하면 다음과 같은 문제가 발생합니다. 다음 출력:
Exception in thread "main" java.lang.OutOfMemoryError: PermGen space at java.lang.String.intern(Native Method) at com.test.RuntimeConstantPoolOOMTest.main(RuntimeConstantPoolOOMTest.java:16)
, 如果通过 JDK1.8 来编译运行上面代码的话, 会有如下警告, 并且不会产生任何的异常:
>>> java -XX:PermSize=10M -XX:MaxPermSize=10M com.test.RuntimeConstantPoolOOMTest 16-10-03 0:23 Java HotSpot(TM) 64-Bit Server VM warning: ignoring option PermSize=10M; support was removed in 8.0 Java HotSpot(TM) 64-Bit Server VM warning: ignoring option MaxPermSize=10M; support was removed in 8.0
메서드 영역의 메모리 오버플로
메서드 영역은 클래스 이름, 클래스 액세스 수정자, 필드 등 클래스 관련 정보를 저장하는 데 사용됩니다. 따라서 메소드 영역이 너무 작고 너무 많은 클래스를 로드하면 메소드 영역의 메모리가 오버플로됩니다.
//VM Args: -XX:PermSize=10M -XX:MaxPermSize=10M public class MethodAreaOOMTest { public static void main(String[] args) { while (true) { Enhancer enhancer = new Enhancer(); enhancer.setSuperclass(MethodAreaOOMTest.class); enhancer.setUseCache(false); enhancer.setCallback(new MethodInterceptor() { public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable { return methodProxy.invokeSuper(o, objects); } }); enhancer.create(); } } }
위 코드에서, 우리는 CGlib를 사용하여 많은 수의 클래스를 동적으로 생성합니다. JDK6에서 위 코드를 실행하면 OutOfMemoryError: PermGen 공간 예외가 생성됩니다:
/System/Library/Frameworks/JavaVM.framework/Versions/1.6/Home /bin/java -jar -XX:PermSize=10M -XX:MaxPermSize=10M target/Test-1.0-SNAPSHOT.jar
출력 결과는 다음과 같습니다.
Caused by: java.lang.OutOfMemoryError: PermGen space at java.lang.ClassLoader.defineClass1(Native Method) at java.lang.ClassLoader.defineClassCond(ClassLoader.java:637) at java.lang.ClassLoader.defineClass(ClassLoader.java:621) ... 11 more
MetaSpace 메모리 오버플로
메서드 영역의 메모리 오버플로 섹션에서 JDK8에는 영구 생성 개념이 없으므로 이 두 예제는 JDK8에서 예상한 결과를 얻지 못했다고 언급했습니다. 메소드 영역 메모리 오버플로 같은 오류도 있죠? 물론 JDK8에서는 MetaSpace 영역을 Class 관련 정보를 저장하는 용도로 사용하기 때문에 MetaSpace 메모리 공간이 부족하면 java.lang.OutOfMemoryError: Metaspace Exception이 발생합니다. 🎜>
위에서 언급한 예를 계속 사용합니다.//VM Args: -XX:MaxMetaspaceSize=10M public class MethodAreaOOMTest { public static void main(String[] args) { while (true) { Enhancer enhancer = new Enhancer(); enhancer.setSuperclass(MethodAreaOOMTest.class); enhancer.setUseCache(false); enhancer.setCallback(new MethodInterceptor() { public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable { return methodProxy.invokeSuper(o, objects); } }); enhancer.create(); } } }
이 예의 코드 부분은 변경되지 않았습니다. 유일한 차이점은 JDK8을 사용하여 이를 실행해야 한다는 것입니다. 코드는 -XX:MaxMetaspaceSize=10M 매개변수로 설정됩니다. 이 매개변수는 Metaspace의 최대 크기가 10M임을 JVM에 알려줍니다.
그런 다음 JDK8을 사용하여 이 예제를 컴파일하고 실행하면 다음 예외가 출력됩니다. :
>>> java -jar -XX:MaxMetaspaceSize=10M target/Test-1.0-SNAPSHOT.jar Exception in thread "main" java.lang.OutOfMemoryError: Metaspace at net.sf.cglib.core.AbstractClassGenerator.generate(AbstractClassGenerator.java:345) at net.sf.cglib.proxy.Enhancer.generate(Enhancer.java:492) at net.sf.cglib.core.AbstractClassGenerator$ClassLoaderData.get(AbstractClassGenerator.java:114) at net.sf.cglib.core.AbstractClassGenerator.create(AbstractClassGenerator.java:291) at net.sf.cglib.proxy.Enhancer.createHelper(Enhancer.java:480) at net.sf.cglib.proxy.Enhancer.create(Enhancer.java:305) at com.test.MethodAreaOOMTest.main(MethodAreaOOMTest.java:22)
위 내용은 일반적인 Java 메모리 오버플로 예외 및 코드 구현 내용입니다. 자세한 내용은 PHP 중국어 웹사이트(www.php.cn)를 참고하세요!

핫 AI 도구

Undresser.AI Undress
사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover
사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool
무료로 이미지를 벗다

Clothoff.io
AI 옷 제거제

AI Hentai Generator
AI Hentai를 무료로 생성하십시오.

인기 기사

뜨거운 도구

PhpStorm 맥 버전
최신(2018.2.1) 전문 PHP 통합 개발 도구

SublimeText3 Linux 새 버전
SublimeText3 Linux 최신 버전

VSCode Windows 64비트 다운로드
Microsoft에서 출시한 강력한 무료 IDE 편집기

ZendStudio 13.5.1 맥
강력한 PHP 통합 개발 환경

메모장++7.3.1
사용하기 쉬운 무료 코드 편집기
