Java 힙은 객체 인스턴스를 저장하는 데 사용됩니다. 따라서 객체를 지속적으로 생성하고 GC 루트와 생성 된 물체 사이에 접근 가능한 경로가 있는지 확인하여 객체를 수집하는 물체를 피하면 너무 많은 객체가 생성되면 힙 메모리가 불충분 해져서 외부에 대한 예외가 발생합니다.
/** * @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를 통해 힙 메모리를 10 메가 바이트로 설정하고 매개 변수 -xx :+heapdumponoutofMemoryError를 사용하여 JVM이 후속 분석을위한 외부 메모리 예외가 발생할 때 현재 메모리 스냅 샷을 인쇄합니다.
위 코드를 컴파일하고 실행 한 후 다음 출력은 다음과 같습니다.
>>> java -xms10m -xmx10m -xx :+heapdumponoutofmemoryerRor com.test.outofMemoryErrortest 16-10-02 23 : 35java.lang.outofMemoryError : java heap heap heap to java_pid1810.hprof가 생성 된 java headumping healing heap in 0.125 초] 스레드에서의 예외 "Main"Java.lang.outofMemoryError : java.util.arrays.copyof (arrays.java:3210)의 Java 힙 공간에서 Java.util.arrays.copyof (arrays.java:3181)의 java.util.arraylist. at Java.util.arraylist.ensureExplicitCapacity (arraylist.java:235) at java.util.arraylist.ensurecapicacity (arraylist.java:227) at java.util.arraylist.add (arraylist.java:458) at com.test.outofmemoryerRortest.main (outofmemoryerRortest.java:15)
Java 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 깊이) {깊이 ++; stackoutofMemoryError (깊이); }}위 코드를 컴파일하고 실행하면 다음 예외 정보가 출력됩니다.
스레드의 예외 "main"java.lang.stackoverflowerror at com.test.outofmemoryerRortest.stackoutofmemoryError (outofMemoryErrortest.java:27)
방법 영역의 메모리 오버플로
JDK8은 영구 생성을 제거하고 JDK8에서 Metaspace로 교체 했으므로 다음 두 가지 예 중 어느 것도 Java.lang.outofMemoryError : Permgen Space Exception을 유발하지 않습니다.
런타임 중에 일정한 수영장 오버플로
Java 1.6 및 이전 버전의 핫스팟 JVM에는 영구 생성 개념, 즉 GC의 생성 수집 메커니즘이 방법 영역으로 확장됩니다. 방법 영역에서 메모리의 일부는 일정한 풀을 저장하는 데 사용됩니다. 따라서 코드에 상수가 너무 많으면 상수 풀의 메모리가 소진되어 메모리 오버플로가됩니다. 그렇다면 상수 수영장에 많은 상수를 추가하는 방법은 무엇입니까? 현재 String.intern () 메소드에 의존해야합니다. String.intern () 메소드의 함수는 다음과 같습니다.이 문자열의 값이 이미 상수 풀에 존재하는 경우이 메소드는 상수 풀의 해당 문자열에 대한 참조를 반환합니다. 그렇지 않으면이 문자열에 포함 된 값을 상수 풀에 추가 하고이 문자열 객체에 대한 참조를 반환하십시오. 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 ++). 인턴 ()); }}}이 예에서는 상수 풀에 많은 수의 문자열 상수를 추가하기 위해 String.intern () 메소드를 정확하게 사용하고 있으며, 이는 상수 풀의 메모리 오버 플로우로 이어집니다.
우리는 JDK1.6을 통해 위의 코드를 컴파일하고 실행하며 다음과 같은 출력이 다음과 같습니다.
스레드 예외 "main"java.lang.outofmemoryerRor : com.test.runtimeconstantpooloomtest.main의 java.lang.string.intern (기본 메소드)의 Permgen 공간 (runtimeconstantpooloomtest.java:16)
위의 코드가 편집되어 JDK1.8을 통해 실행되면 다음 경고가 발생하며 예외는 생성되지 않습니다.
>>> java -xx : permsize = 10m -xx : maxpermsize = 10m com.test.runtimeconstantpooloomtest 16-10-03 0 : 23java 핫스팟 (TM) 64 비트 서버 VM 경고 : 옵션 permsize = 10m; 8.0 Java Hotspot (TM) 64 비트 서버 VM 경고에서 지원이 제거되었습니다. 옵션 MaxPermsize = 10m; 지지는 8.0에서 제거되었습니다
방법 영역의 메모리 오버플로
메소드 영역의 기능은 클래스 이름, 클래스 액세스 수정 자, 필드 설명, 메소드 설명 등과 같은 클래스의 관련 정보를 저장하는 것입니다. 따라서 메소드 영역이 너무 작고 너무 많은 클래스가로드되면 메소드 영역의 메모리 오버플로.
// vm args : -xx : permsize = 10m -xx : maxpermsize = 10mpublic 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, Objects, MethodProxy MethodProxy) 던질 가능 {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
출력 결과는 다음과 같습니다.
원인 : Java.lang.outofMemoryError : java.lang.classlass1 (java.lang.classloader.defineclasscond)의 java.lang.classlader.defineclass1 (기본 메소드)의 Permgen 공간 (java.lang.classloader.defineclass) ....java:621).
Metaspace 메모리 오버플로
방법 영역의 메모리 오버 플로우 메모리 오버 플로우 섹션에서, 우리는 JDK8에 영구 생성 개념이 없으므로이 두 예제는 JDK8에서 예상 효과를 달성하지 못했다고 언급했습니다. JDK8에서는 메소드 영역에 메모리 오버플로와 같은 오류가 있습니까? 물론 일부. JDK8에서 Metaspace 영역은 클래스 관련 정보를 저장하는 데 사용되므로 Metaspace가 불충분하면 java.lang.outofMemoryError : Metaspace Exception이 발생합니다.
위에서 언급 한 예를 예로 들어 보겠습니다.
// vm args : -xx : maxmetaspacesize = 10mpublic class methodareaoomtest {public static void main (string [] args) {while (true) {enterancer enhancer = new enhancer (); Enhancer.SetSuperClass (MethodAreaoomtest.class); Enhancer.setUsecache (false); Enhancer.setCallback (new MethodInterceptor () {public Object Intercept (Object O, Method Method, Objects, MethodProxy MethodProxy) 던질 가능 {return MethodProxy.inVokesUper (O, Objects);}}); Enhancer.create (); }}}이 예제의 코드 부분은 변경되지 않았습니다. 유일한 차이점은 JDK8을 사용 하여이 코드를 실행하고 매개 변수 -xx : maxmetaspacesize = 10m을 설정해야한다는 것입니다. 이 매개 변수는 JVM에 Metaspace의 최대 크기가 10m임을 알려줍니다.
그런 다음 JDK8을 사용 하여이 예제를 컴파일하고 실행하고 다음과 같은 예외를 출력합니다.
>>> java -jar -xx : maxmetaspacesize = 10m target/test/test -1.0-snapshot.jarexception 스레드 "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)의 net.sf.cglib.core.abtractclassgenerator $ classloaderdata.get (AbstractClassGenerator.java:114) at net.sf.cglib.core.abstractclassgenerator.create (atbractclassgenerator.java:291)에서 net.sf.cglib.proxy.enhancer.createhelper (Enhancer.java:480)의 net.sf.cglib.proxy.enhancer.create com.test.methodareaoomtest.main (Methodareaoomtest.java:22)
요약
위의 내용은 공통 메모리 오버플로 예외와 코드 예제에 관한 것이며,이 기사의 코드 예제입니다. 모든 사람에게 도움이되기를 바랍니다. 관심있는 친구는이 사이트의 다른 관련 주제를 계속 참조 할 수 있습니다. 단점이 있으면 메시지를 남겨 두십시오. 이 사이트를 지원해 주신 친구들에게 감사드립니다!