자바 메모리 넘 침 실현 원인 및 솔 루 션
JVM 은 시작 할 때 JVM Heap 의 값 을 자동 으로 설정 하 며,JVM 이 제공 하 는-Xmn-Xms-Xmx 등의 옵션 을 이용 하여 설정 할 수 있 습 니 다.힙 의 크기 는 Young Generation 과 Tenured Generaion 의 합 이다.JVM 에서 98%의 시간 이 GC 에 사용 되 고 사용 가능 한 Heap size 가 2%미 만인 경우 이 이상 정 보 를 던 집 니 다.
해결 방법:JVM Heap(더미)의 크기 를 수 동 으로 설정 합 니 다.
자바 더 미 는 대상 인 스 턴 스 를 저장 하 는 데 사 용 됩 니 다.대상 인 스 턴 스 를 위해 메모 리 를 할당 해 야 할 때,쌓 인 메모리 사용량 은-Xmx 설정 의 최대 값 에 이 르 렀 습 니 다.OutOf Memory Error 이상 을 던 집 니 다.예 는 다음 과 같다.
package com.demo.test;
import java.util.ArrayList;
import java.util.List;
/**
* VM Args: -Xms5m -Xmx5m
*/
public class HeapOOM {
public static void main(String[] args) {
int count = 0;
List<Object> list = new ArrayList<Object>();
while(true){
list.add(new Object());
System.out.println(++count);
}
}
}
그리고 실행 할 때 jvm 인 자 를 설정 합 니 다.다음 과 같 습 니 다.-Xmx 는 5m.그 중 한 번 의 테스트 결 과 는 count 의 값 이 360145 까지 누적 되면 다음 과 같은 이상 이 발생 합 니 다.
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space at java.util.Arrays.copyOf(Arrays.java:2245) at java.util.Arrays.copyOf(Arrays.java:2219) at java.util.ArrayList.grow(ArrayList.java:213) at java.util.ArrayList.ensureCapacityInternal(ArrayList.java:187) at java.util.ArrayList.add(ArrayList.java:411) at com.demo.test.HeapOOM.main(HeapOOM.java:12)
수정-Xmx 10m.이 중 한 번 의 테스트 결 과 는 count 의 값 이 540217 까지 누적 되 었 을 때 OutOf Memory Error 이상 이 발생 한 것 으로 나 타 났 다.-Xmx 매개 변수 값 이 커지 면서 자바 더미 에 저장 할 수 있 는 대상 도 많 습 니 다.
2.PermGen space 넘 침:java.lang.OutOfmoryError:PermGen space
PermGen space 의 전 칭 은 Permanent Generation space 로 메모리 의 영구 저장 영역 을 말한다.메모리 가 넘 치 는 이 유 는 JVM 이 주로 Class 와 Meta 정 보 를 저장 하기 때 문 입 니 다.Class 는 Load 될 때 PermGen space 영역 에 들 어 갑 니 다.Instance 를 저장 하 는 Heap 영역 과 달리 sun 의 GC 는 주 프로그램 실행 기간 에 PermGen space 를 정리 하지 않 기 때문에 앱 이 CLASS 를 많이 불 러 옵 니 다.PermGen space 가 넘 칠 수 있 습 니 다.일반적으로 프로그램의 시작 단계 에서 발생 한다.
해결 방법:-XX:PermSize 와-XX:MaxPermSize 를 통 해 영구 세대 크기 를 설정 하면 됩 니 다.
방법 구역 은 자바 형식의 관련 정 보 를 저장 하 는 데 사 용 됩 니 다.예 를 들 어 클래스 이름,방문 수정자,상수 탱크,필드 설명,방법 설명 등 입 니 다.클래스 로 더 가 class 파일 을 메모리 에 불 러 오 는 과정 에서 가상 기 회 는 그 중의 유형 정 보 를 추출 하고 이 정 보 를 방법 구역 에 저장 합 니 다.클래스 정 보 를 저장 해 야 하고 방법 구역 의 메모리 사용량 이-XX:MaxPermSize 설정 의 최대 값 에 이 르 렀 을 때 OutOfmory Error 이상 을 던 집 니 다.이런 상황 에 대한 테스트 에 있어 기본 적 인 사 고 는 운행 할 때 대량의 유형 이 방법 구역 을 채 우 고 넘 칠 때 까지 하 는 것 이다.CGLib 를 통 해 바이트 코드 를 직접 조작 해 야 할 때 대량의 동적 클래스 가 생 성 되 었 습 니 다.예 는 다음 과 같다.
package com.demo.test;
import java.lang.reflect.Method;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodProxy;
import net.sf.cglib.proxy.MethodInterceptor;
/**
* VM Args: -XX:PermSize=10M -XX:MaxPermSize=10M
*/
public class MethodAreaOOM {
public static void main(String[] args) {
int count = 0;
while (true) {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(MethodAreaOOM.class);
enhancer.setUseCache(false);
enhancer.setCallback(new MethodInterceptor() {
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
return proxy.invoke(obj, args);
}
});
enhancer.create();
System.out.println(++count);
}
}
}
-XX:MaxPerm Size 는 10m 입 니 다.그 중 한 번 의 테스트 결 과 는 count 의 값 이 800 까지 누적 되면 다음 과 같은 이상 이 발생 합 니 다.Caused by: java.lang.OutOfMemoryError: PermGen space at java.lang.ClassLoader.defineClass1(Native Method) at java.lang.ClassLoader.defineClass(ClassLoader.java:792) ... 8 more
-XX:MaxPermSize 매개 변수 값 이 커지 면서 자바 방법 구역 에 저장 할 수 있 는 형식 데이터 도 많 습 니 다.3.스 택 넘 침:java.lang.StackOverflow 오류:Thread Stack space
스 택 이 넘 쳤 습 니 다.JVM 은 여전히 스 택 식 가상 머 신 을 사용 합 니 다.이것 은 C 와 Pascal 과 같 습 니 다.함수 의 호출 과정 은 모두 창고 와 창고 에서 나 타 났 다.구조 함 수 를 호출 하 는'층'이 너무 많아 서 스 택 구역 이 넘 쳤 습 니 다.일반적으로 일반 스 택 구역 은 쌓 인 구역 보다 훨씬 작 습 니 다.함수 호출 과정 이 수천 층 보다 많 지 않 기 때문에 모든 함수 호출 에 1K 의 공간 이 필요 하 더 라 도(이것 은 한 C 함수 에서 256 개의 int 형식의 변 수 를 설명 하 는 것 과 같 습 니 다)스 택 구역 은 1MB 의 공간 이 필요 합 니 다.보통 창고 의 크기 는 1-2MB 이다.쉽게 말 하면 단일 스 레 드 프로그램 에 필요 한 메모리 가 너무 크다 는 것 이다.일반적으로 재 귀적 으로 도 재 귀적 인 차원 이 너무 많 으 면 넘 치기 쉽다.
해결 방법:1:프로그램 수정.2:-Xss:를 통 해 각 스 레 드 의 Stack 크기 를 설정 하면 됩 니 다.
자바 가상 컴퓨터 규범 에서 이 지역 에 대해 두 가지 이상 상황 을 규정 했다.StackOverflow Error 와 OutOf Memory Error 이상 이다.
(1)StackOverflow 오류 이상
자바 프로그램 코드 가 새 스 레 드 를 시작 할 때마다 자바 가상 머 신 은 자바 스 택 을 할당 합 니 다.자바 스 택 은 프레임 단위 로 스 레 드 의 운행 상 태 를 저장 합 니 다.스 레 드 가 자바 방법 을 호출 할 때 가상 머 신 은 이 스 레 드 의 자바 스 택 에 새 스 택 프레임 을 누 릅 니 다.이 방법 이 아직 돌아 오지 않 았 다 면 그것 은 줄곧 존재 할 것 이다.
만약 에 스 레 드 방법 이 플러그 인 호출 차원 이 너무 많 으 면(예 를 들 어 재 귀적 호출)자바 스 택 의 프레임 이 점점 증가 함 에 따라 최종 적 으로 이 스 레 드 자바 스 택 의 모든 스 택 프레임 크기 가-Xss 설정 값 보다 크 기 때문에 StackOverflow Error 메모리 에 이상 이 생 길 수 있 습 니 다.예 는 다음 과 같다.
package com.demo.test;
/**
* VM Args: -Xss128k
*/
public class JavaVMStackSOF {
private int count = 0;
public static void main(String[] args) {
new JavaVMStackSOF().method();
}
public void method() {
System.out.println(++count);
method();
}
}
-Xss 는 128 k.그 중 한 번 의 테스트 결 과 는 count 의 값 이 2230 까지 누적 되면 다음 과 같은 이상 이 발생 합 니 다.Exception in thread "main" java.lang.StackOverflowError at sun.nio.cs.UTF_8.updatePositions(UTF_8.java:77) at sun.nio.cs.UTF_8$Encoder.encodeArrayLoop(UTF_8.java:564) at sun.nio.cs.UTF_8$Encoder.encodeLoop(UTF_8.java:619) at java.nio.charset.CharsetEncoder.encode(CharsetEncoder.java:561) at sun.nio.cs.StreamEncoder.implWrite(StreamEncoder.java:271) at sun.nio.cs.StreamEncoder.write(StreamEncoder.java:125) at java.io.OutputStreamWriter.write(OutputStreamWriter.java:207) at java.io.BufferedWriter.flushBuffer(BufferedWriter.java:129) at java.io.PrintStream.write(PrintStream.java:526) at java.io.PrintStream.print(PrintStream.java:597) at java.io.PrintStream.println(PrintStream.java:736) at com.demo.test.JavaVMStackSOF.method(JavaVMStackSOF.java:15)
-Xss 매개 변수 값 이 커지 면서 끼 워 넣 을 수 있 는 방법 호출 차원 도 상응 하 게 증가 합 니 다.다시 말하자면 StackOverflow Error 이상 은 방법 호출 의 차원 이 너무 깊 어서 최종 적 으로 특정한 스 레 드 에 분 배 된 모든 스 택 프레임 의 크기 가-Xss 설정 의 값 보다 커서 StackOverflow Error 이상 이 발생 한 것 이다.
(2)OutOfmory 오류 이상
자바 프로그램 코드 가 새 스 레 드 를 시작 할 때 이 스 레 드 에 자바 스 택 을 할당 할 충분 한 메모리 공간 이 없습니다.예 는 다음 과 같다.
package com.demo.test;
/**
* VM Args: -Xss128k
*/
public class JavaVMStackOOM {
public static void main(String[] args) {
int count = 0;
while (true) {
Thread thread = new Thread(new Runnable() {
public void run() {
while (true) {
try {
Thread.sleep(5000);
} catch (Exception e) {
}
}
}
});
thread.start();
System.out.println(++count);
}
}
}
-Xss 는 128 k.그 중 한 번 의 테스트 결 과 는 count 의 값 이 11958 까지 누적 되면 다음 과 같은 이상 이 발생 합 니 다.Exception in thread "main" java.lang.OutOfMemoryError: unable to create new native thread
at java.lang.Thread.start0(Native Method)
at java.lang.Thread.start(Thread.java:693)
at com.demo.test.JavaVMStackOOM.main(JavaVMStackOOM.java:21)
-Xss 매개 변수 값 이 커지 면서 자바 프로그램 이 만 들 수 있 는 버스 프로 세 스 가 적 습 니 다.
4.그래서 서버 용기 가 시 작 될 때 우 리 는 항상 JVM 의 몇 가지 인 자 를 다음 과 같이 관심 을 가지 고 설정 합 니 다.
첫 번 째 OutOf Memory Error:PermGen space
이러한 문제 가 발생 한 원 의 는 프로그램 에서 대량의 jar 나 class 를 사용 하여 자바 가상 컴퓨터 로 딩 류 의 공간 이 부족 하고 Permanent Generation space 와 관련 이 있다 는 것 이다.이런 문 제 를 해결 하 는 데 는 다음 과 같은 두 가지 방법 이 있다.
1.자바 가상 컴퓨터 의 XX:PermSize 와 XX:MaxPermSize 매개 변수의 크기 를 증가 합 니 다.그 중에서 XX:PermSize 는 초기 영구 저장 영역 크기 이 고 XX:MaxPermSize 는 최대 영구 저장 영역 크기 입 니 다.tomcat 6.0 을 대상 으로 catalina.sh 또는 catalina.bat 파일 에서 일련의 환경 변수 이름 설명 끝 부분(약 70 줄 정도)에 한 줄 추가:JAVAOPTS='-XX:PermSize=64M-XX:MaxPermSize=128 m'윈도 우즈 서버 라면 시스템 환경 변수 에 도 설정 할 수 있다.tomcat 로 sprint+struts+hibenate 구 조 를 발표 할 때 이러한 메모리 넘 침 오류 가 발생 하기 쉽다 고 생각 합 니 다.상기 방법 을 사용 하여 저 는 ssh 프로젝트 를 배치 하 는 tomcat 서버 가 자주 지연 되 는 문 제 를 성공 적 으로 해결 하 였 습 니 다.
2.응용 프로그램 에서 웹-inf/lib 의 jar 를 청소 합 니 다.만약 에 tomcat 에 여러 개의 응용 프로그램 을 배치 하면 많은 응용 프로그램 이 같은 jar 를 사용 합 니 다.공 통 된 jar 를 tomcat 의 공 통 된 lib 로 옮 겨 서 클래스 의 중복 로드 를 줄 일 수 있 습 니 다.이런 방법 은 인터넷 에서 일부 사람들 이 추천 한 것 이다.나 는 해 본 적 이 없 지만 큰 공간 을 줄 일 수 없다 고 느낀다.가장 믿 을 만 한 것 은 역시 첫 번 째 방법 이다.
두 번 째 OutOfmoryError:Java heap space
이러한 문제 가 발생 한 이 유 는 자바 가상 컴퓨터 가 만 든 대상 이 너무 많 기 때 문 입 니 다.쓰레기 수 거 를 하 는 동안 가상 컴퓨터 가 분 배 된 메모리 공간 이 이미 꽉 찼 기 때 문 입 니 다.Heap space 와 관련 이 있 습 니 다.이런 문 제 를 해결 하 는 데 는 두 가지 사고방식 이 있다.
1.프로그램 을 검사 하고 순환 이 없 거나 불필요 하 게 대량의 대상 을 만 드 는 지 확인 합 니 다.원인 을 찾 은 후 프로그램 과 알고리즘 을 수정 합 니 다.제 가 예전 에 K-Means 텍스트 클 러 스 터 알고리즘 을 사용 하여 몇 만 개의 텍스트 기록(각 기록 의 특징 벡터 는 약 10 개)을 텍스트 클 러 스 터 로 만 들 었 을 때 프로그램의 디 테 일 에 문제 가 있어 자바 힙 스페이스 의 메모리 넘 침 문 제 를 초래 했 고 나중에 수정 프로그램 을 통 해 해결 되 었 습 니 다.
2.자바 가상 컴퓨터 에서 Xms(초기 더미 크기)와 Xmx(최대 더미 크기)매개 변수의 크기 를 증가 합 니 다.set JAVAOPTS= -Xms256m -Xmx1024m
이상 이 바로 본 고의 모든 내용 입 니 다.여러분 의 학습 에 도움 이 되 고 저 희 를 많이 응원 해 주 셨 으 면 좋 겠 습 니 다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
JPA + QueryDSL 계층형 댓글, 대댓글 구현(2)이번엔 전편에 이어서 계층형 댓글, 대댓글을 다시 리팩토링해볼 예정이다. 이전 게시글에서는 계층형 댓글, 대댓글을 구현은 되었지만 N+1 문제가 있었다. 이번에는 그 N+1 문제를 해결해 볼 것이다. 위의 로직은 이...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.