java.lang 잡는 중Out Of Memory Error?
문서:java.lang.Error
라고 말합니다
오류는 적절한 응용 프로그램이 탐지하지 않아야 하는 심각한 문제를 나타내는 Throwable의 하위 클래스입니다.
지.........java.lang.Error
는 의 입니다.java.lang.Throwable
나는 이런 종류의 던질 수 있는 것을 잡을 수 있다.
왜 이런 종류의 예외를 잡는 것이 좋지 않은지 이해합니다.내가 알기론, 만약 우리가 그것을 잡기로 결정한다면, 캐치 핸들러는 그 자체로 어떤 메모리도 할당하지 말아야 한다. 이외의 경우는, 「」입니다.OutOfMemoryError
시시시던던던다
자, 제 질문은 다음과 같습니다.
- " " " " " " " " " " " " " " " 를 잡을 때 실제 가 있나요?
java.lang.OutOfMemoryError
은생 ?? - 로
java.lang.OutOfMemoryError
캐치 핸들러가 메모리 자체를 할당하지 않도록 하려면 어떻게 해야 합니까(도구나 베스트 프랙티스).
.OutOfMemoryError
및 Solaris 드물게 ( "Solaris JVM")가 됩니다.OutOfMemoryError
JVM j j j j j j
데는 딱 한 .OutOfMemoryError
즉, 리소스를 정상적으로 종료하고 가능한 한 깨끗하게 해방하여 장애의 원인을 기록합니다(가능한 경우).
「」의OutOfMemoryError
는 블록 메모리 할당이 히프의 나머지 리소스로 만족할 수 없기 때문에 발생합니다.
?Error
this rown 에는 할당에 실패하기 전과 동일한 양의 할당 객체가 포함되어 있습니다.이 시점에서 런타임 객체에 대한 참조를 드롭하여 청소에 필요한 메모리를 더 확보할 수 있습니다.이 경우 계속 진행할 수도 있지만 JVM이 복구 가능한 상태인지 100% 확신할 수 없기 때문에 이는 확실히 잘못된 생각입니다.
★★★★★의 데모OutOfMemoryError
JVM의 캐치블록 메모리가 부족하다는 의미는 아닙니다.
private static final int MEGABYTE = (1024*1024);
public static void runOutOfMemory() {
MemoryMXBean memoryBean = ManagementFactory.getMemoryMXBean();
for (int i=1; i <= 100; i++) {
try {
byte[] bytes = new byte[MEGABYTE*500];
} catch (Exception e) {
e.printStackTrace();
} catch (OutOfMemoryError e) {
MemoryUsage heapUsage = memoryBean.getHeapMemoryUsage();
long maxMemory = heapUsage.getMax() / MEGABYTE;
long usedMemory = heapUsage.getUsed() / MEGABYTE;
System.out.println(i+ " : Memory Use :" + usedMemory + "M/" +maxMemory+"M");
}
}
}
이 코드의 출력:
1 : Memory Use :0M/247M
..
..
..
98 : Memory Use :0M/247M
99 : Memory Use :0M/247M
100 : Memory Use :0M/247M
을 할 .Error
후 pathion으로 .syserr는 Clean pathion으로 무슨 일이 일어날 수 있는 가장 나쁜 일인가요? 정지중)이며, 「JVM」(「JVM」)을 으로써,Error
적어도 청소할 기회는 있다.
주의: 이러한 유형의 오류는 청소가 가능한 장소에서만 탐지해야 합니다.catch(Throwable t) {}
★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
회복할 수 있습니다.
package com.stackoverflow.q2679330;
public class Test {
public static void main(String... args) {
int size = Integer.MAX_VALUE;
int factor = 10;
while (true) {
try {
System.out.println("Trying to allocate " + size + " bytes");
byte[] bytes = new byte[size];
System.out.println("Succeed!");
break;
} catch (OutOfMemoryError e) {
System.out.println("OOME .. Trying again with 10x less");
size /= factor;
}
}
}
}
하지만 말이 되나요?또 뭐 하고 싶어요?처음에 그렇게 많은 메모리를 할당한 이유는 무엇입니까?메모리는 적게 해도 괜찮습니까?어쨌든 벌써 써먹지 그래?아니면 처음부터 JVM에 더 많은 메모리를 제공하는 것이 어떨까요?
질문으로 돌아가기:
1: java.http를 잡을 때 실제 단어 시나리오가 있습니까?Out Of Memory Error가 좋은 생각일까요?
아무것도 생각나지 않는다.
2: java.disclock을 잡으면.Out Of Memory Error 캐치 핸들러가 메모리 자체를 할당하지 않도록 하려면 어떻게 해야 합니까(도구나 베스트 프랙티스).
OOME에서 try
차근차근 일어난 일이라 가능성이 적어요메모리 공간을 미리 예약할 수 있습니다.
private static byte[] reserve = new byte[1024 * 1024]; // Reserves 1MB.
OOE 중에 0으로 설정합니다.
} catch (OutOfMemoryException e) {
reserve = new byte[0];
// Ha! 1MB free!
}
물론, 이것으로 모든 것이 무의미해집니다.) 어플리케이션의 요구에 따라 JVM에 충분한 메모리를 제공합니다.필요에 따라 프로파일러를 실행합니다.
일반적으로 OOM을 잡고 회복하려고 하는 것은 좋지 않은 생각입니다.
OOE는 어플리케이션이 인식하지 못하는 스레드 등 다른 스레드에도 투입될 수 있습니다.이러한 스레드는 모두 종료되고 알림을 기다리고 있던 스레드는 영원히 정지될 수 있습니다.즉, 앱이 중단될 수 있습니다.
복구에 성공하더라도 JVM은 여전히 힙 부족에 시달리고 그 결과 애플리케이션의 성능이 저하될 수 있습니다.
OOE를 사용하는 가장 좋은 방법은 JVM을 정지시키는 것입니다.
(이것은, JVM이 정지하는 것을 전제로 하고 있습니다.예를 들어 Tomcat servlet 스레드의 OOM은 JVM을 종료하지 않으며, 이로 인해 Tomcat은 어떤 요청에도 응답하지 않는 긴장 상태가 됩니다.재기동 요구도 없습니다.)
편집
OOM을 잡는 것이 전혀 나쁜 생각이라고 말하는 것이 아닙니다.이 문제는 OOE에서 의도적으로 또는 실수로 회복하려고 할 때 발생합니다.OOM을 잡을 때마다(직접 또는 Error 또는 Throughable의 서브타입으로) 재투입하거나 애플리케이션/JVM을 종료하도록 준비해야 합니다.
기타: 이는 OOM에서 최대한의 견고성을 얻으려면 응용 프로그램에서 스레드를 사용해야 함을 나타냅니다.setDefaultUncaughtExceptionHandler()를 사용하여 OOE 발생 시 응용 프로그램을 종료하는 핸들러를 설정합니다.이 핸들러는 OOE가 어떤 스레드에 느려지든 상관없습니다.이 문제에 대한 의견을 듣고 싶습니다만...
유일한 시나리오는 OOM이 부수적인 손상을 초래하지 않았다는 것을 확실히 알고 있는 경우입니다.즉, 다음과 같습니다.
- 구체적으로 무엇이 OOE의 원인이 되었는지,
- 어플리케이션이 그 당시에 무엇을 하고 있었는지, 그리고 그 계산은 단순히 폐기해도 괜찮은지, 그리고
- 다른 스레드에서 (거의) 동시 OOE가 발생했을 리가 없습니다.
이러한 정보를 알 수 있는 어플리케이션도 있습니다만, 대부분의 어플리케이션에서는 OOE 이후의 계속이 안전한지 확인할 수 없습니다.시도했을 때 경험적으로 효과가 있다고 해도.
(문제는 "예상된" OOE의 결과가 안전하다는 것과 "예상하지 않은" OOE가 시행/획득된 OOE의 통제 내에서 발생할 수 없다는 것을 보여주기 위해 공식적인 증거가 필요하다는 것입니다.)
네, 실제 시나리오가 있습니다.여기 제 것이 있습니다.노드당 메모리가 제한된 클러스터에서 매우 많은 항목의 데이터 세트를 처리해야 합니다.지정된 JVM 인스턴스는 여러 항목을 차례로 처리하지만 일부 항목은 너무 커서 클러스터에서 처리할 수 없습니다.내가 잡을 수 있어OutOfMemoryError
어떤 아이템이 너무 큰지 주의해 주세요.나중에 RAM이 더 많은 컴퓨터에서 큰 항목만 다시 실행할 수 있습니다.
(1개의 어레이에 수 기가바이트의 할당이 실패하기 때문에 오류를 검출한 후에도 JVM은 정상이며 다른 항목을 처리할 수 있는 충분한 메모리가 있습니다.)
OOE를 잡는 것이 의미가 있는 시나리오는 분명 있습니다.IDEA 에서는, 기동 메모리 설정을 변경할 수 있는 다이얼로그가 표시됩니다(이후 종료합니다).응용 프로그램서버가 그것들을 검출해 보고하는 경우가 있습니다.이 작업의 열쇠는 디스패치에 대해 높은 수준에서 실행하는 것입니다.그러면 예외를 포착한 시점에서 대량의 자원을 해방할 수 있는 적절한 기회가 생깁니다.
위의 IDEA 시나리오 외에 일반적으로 캐치는 OOM뿐만 아니라 슬로우 가능이어야 하며 적어도 스레드가 곧 종료되는 컨텍스트에서 수행되어야 합니다.
물론 대부분의 경우 메모리가 부족하여 복구할 수 없지만, 이 방법이 타당합니다.
제 경우 Out Of Memory Error를 잡는 것이 좋은 방법인지 궁금해서 이 질문을 하게 되었습니다.이 에러를 발견했을 때, 또 다른 예를 들면, 다른 사람이 납득할 수 있는 것인지, 또 한편으로 그것이 정말로 좋은 아이디어인지 아닌지를 확인하기 위해서입니다(저는 우버 주니어 개발자이기 때문에, 쓰는 코드의 어느 행에도 그다지 확신이 서지 않습니다).
어쨌든, 메모리 사이즈가 다른 디바이스에서 실행할 수 있는 Android 어플리케이션을 만들고 있습니다.위험한 부분은 파일에서 비트맵을 디코딩하여 ImageView인스턴스에 표시하는 것입니다.디코딩된 비트맵의 크기 면에서 더 강력한 장치를 제한하고 싶지도 않고, 메모리가 매우 적은 오래된 장치에서 앱이 실행되지 않을지도 확신할 수 없습니다.그래서 이렇게 합니다.
BitmapFactory.Options bitmapOptions = new BitmapFactory.Options();
bitmapOptions.inSampleSize = 1;
boolean imageSet = false;
while (!imageSet) {
try {
image = BitmapFactory.decodeFile(filePath, bitmapOptions);
imageView.setImageBitmap(image);
imageSet = true;
}
catch (OutOfMemoryError e) {
bitmapOptions.inSampleSize *= 2;
}
}
이를 통해 사용자의 요구와 기대에 따라 점점 더 강력한 기기를 제공할 수 있습니다.
Out Of Memory Error에서 복구해야 하는 응용 프로그램이 있으며, 싱글 스레드 프로그램에서는 항상 작동하지만 멀티 스레드 프로그램에서는 작동하지 않을 수 있습니다.어플리케이션은 자동화된 Java 테스트툴로 생성된 테스트시퀀스를 테스트클래스에서 최대한 깊이까지 실행합니다.이제 UI는 안정적이어야 하지만 테스트 엔진의 메모리가 부족하여 테스트 사례 트리가 커질 수 있습니다.저는 테스트 엔진에서 다음과 같은 코드 관용어로 이 문제를 해결합니다.
boolean isOutOfMemory = false; // 보고에 사용되는 플래그{을(를) 시험해 보다SomeType largeVar;// largeVar에 점점 더 많은 것을 할당하는 메인 루프// 정상 종료 또는 Out Of Memory Error 발생}catch(Out Of Memory Error ex) {// largeVar가 범위를 벗어남과 동시에 가비지가 됩니다.System.gc(); // largeVar 데이터 정리isOutOfMemory = true; // 플래그 사용 가능}// 프로그램이 플래그를 테스트하여 복구를 보고합니다.
이 스레드 응용 프로그램에서 매번 나타난다.그러나 최근 UI에서 분리된 worker-thread에 내 시험 엔진을 장착했습니다.이제 기억 속에서 임의로 두 스레드에서, 이것은 나에게 어떻게 그것을 잡기로 명확하지 않다 발생할 수 있다.
반면 움직이는 GIF내 UI의 프레임은 막후는 내 통제 밖인 것은 스윙 클래스에서 만들어진 독점적 스레드에 의해 상기 동작이 있었던 것으로 예를 들어 나는 OOME 일어났다.나는 보겠지만, 분명히는 애니메이터 그것은 다음 이미지를 가지고 올 때마다 기억을 할당하고 있는 모든 리소스 사전에 필요한 할당된 생각했다.만약 누군가 어떻게 OOMEs 스레드에서 자라 다룰 것인가에 대해 생각이 있고, 나는 듣고 싶은데
네, 진짜 질문은"너는 예외 처리기에서 할 거니?" 있다.거의 모든 것 유용한 동안, 당신은 더 많은 메모리를 할당할 것이다.만약 당신이 전달할 때 OutOfMemoryError하던 진단 일을 하고 싶어요, 당신은 사용할 수 있다.-XX:OnOutOfMemoryError=<cmd>
바늘이 끼이고는 HotSpot VM에서 제공하다.때 OutOfMemoryError 발생하다가 뭔가 유용한 자바의 더미 밖에서 할 수 있는 command(s)실행할 것이다.당신은 정말 기억 속에서 애초에 달리기에서 응용 프로그램을 유지하기 위해 그렇게 그게 왜 일어나는지 찾는 것이다 첫번째 단계에요.그럼은 해당 시 MaxPermSize 더미 크기를 늘릴 수 있다.여기 몇가지 다른 유용한 HotSpot 고리: 있다.
-XX:+PrintCommandLineFlags
-XX:+PrintConcurrentLocks
-XX:+PrintClassHistogram
이곳 표를 참조하십시오.
한 OOME지만, 보통 그것은 '가 될, 언제, 그리고 얼마나 많은 더미 기억 그 시간에 의해 남겨진는 catch블록에 도달하면 자바 가상 머신 지원 일부 개체 garbage-collect 수 있는 것에 맞추어 가면서는 검거할 수 있다.
예: JVM에서 이 프로그램은 끝까지 실행됩니다.
import java.util.LinkedList;
import java.util.List;
public class OOMErrorTest {
public static void main(String[] args) {
List<Long> ll = new LinkedList<Long>();
try {
long l = 0;
while(true){
ll.add(new Long(l++));
}
} catch(OutOfMemoryError oome){
System.out.println("Error catched!!");
}
System.out.println("Test finished");
}
}
단, 캐치블록에 한 줄만 추가하면 무슨 말인지 알 수 있습니다.
import java.util.LinkedList;
import java.util.List;
public class OOMErrorTest {
public static void main(String[] args) {
List<Long> ll = new LinkedList<Long>();
try {
long l = 0;
while(true){
ll.add(new Long(l++));
}
} catch(OutOfMemoryError oome){
System.out.println("Error caught!!");
System.out.println("size:" +ll.size());
}
System.out.println("Test finished");
}
}
첫 번째 프로그램은 정상적으로 실행됩니다.왜냐하면 캐치 블록에 도달하면 JVM이 목록이 더 이상 사용되지 않음을 감지하기 때문입니다(이 탐지는 컴파일 시 최적화될 수도 있습니다).따라서 프린트 스테이트먼트에 도달하면 힙메모리는 거의 해방되어 있기 때문에 작업을 계속할 수 있습니다.이게 가장 좋은 경우야.
단, 리스트와 같이 코드가 정렬되어 있는 경우ll
OOE가 포착되면 JVM이 수집할 수 없게 됩니다.이것은 두 번째 단편에서 발생합니다.새로운 Long 생성에 의해 트리거된 OOE는 포착되지만 곧 새로운 오브젝트(의 문자열)를 만듭니다.System.out.println
line) 및 힙이 거의 가득 차서 새로운 OOE이 느려집니다.이것은 최악의 시나리오입니다.새로운 오브젝트를 작성하려고 했지만 실패하여 OOE를 잡았습니다.그러나 새로운 힙메모리를 필요로 하는 첫 번째 명령(예를 들어 새로운 오브젝트 작성)은 새로운 OOE를 던집니다.이 시점에서 메모리가 거의 남아 있지 않기 때문에 이 시점에서 무엇을 할 수 있을까요?아마 그냥 나가는 거겠지 그래서 쓸모없다고 했지
JVM이 리소스를 가비지 수집하지 않는 이유 중 하나는 다른 스레드가 있는 공유 리소스도 리소스를 사용하는 것입니다.실험적이지 않은 앱에 추가된다면 OOE를 잡는 것이 얼마나 위험한지 누구나 알 수 있다.
Windows x86 32비트 JVM(JRE6)을 사용하고 있습니다.각 Java 앱의 기본 메모리는 64MB입니다.
OOM 에러를 검출하는 유일한 이유는 사용하지 않는 대규모 데이터 구조를 가지고 있기 때문에 null로 설정하여 메모리를 해방할 수 있기 때문입니다.하지만 (1) 기억력을 낭비하고 있다는 것을 의미하며, OOE 후에 절름거리지 말고 코드를 수정해야 합니다.또 (2) 코드를 잡았더라도 어떻게 해야 할까요?OOM은 언제든지 발생할 수 있으며 모든 것이 반쯤 완료되어 있을 수 있습니다.
질문 2에 대해서는 BalusC가 제안하는 해결책을 이미 알고 있습니다.
- java.lang을 잡을 때 실제 단어 시나리오가 있나요?Out Of Memory Error가 좋은 생각일까요?
방금 좋은 예를 발견한 것 같아요.awt 응용 프로그램이 메시지를 디스패치할 때 uncatched Out Of Memory Error가 stderr에 표시되고 현재 메시지 처리가 중지됩니다.하지만 응용 프로그램은 계속 실행됩니다!사용자는 백그라운드에서 발생하는 심각한 문제를 인식하지 못한 채 다른 명령을 발행할 수 있습니다.특히 표준오차를 관찰할 수 없거나 관찰하지 못할 경우.따라서 예외를 포착하고 애플리케이션 재시작을 제공하는(또는 권장하는) 것이 바람직합니다.
Out Of Memory Error를 검출하는 것이 타당하다고 생각되는 시나리오가 있습니다.
시나리오: Android 앱에서는 가능한 한 높은 해상도로 여러 비트맵을 표시하고, 그것들을 유창하게 줌할 수 있도록 하고 싶다.
줌이 유창해서 비트맵을 메모리에 넣고 싶다.그러나 안드로이드는 기기에 의존하여 제어하기 어려운 메모리에 한계가 있습니다.
이 경우 비트맵을 읽는 동안 Out Of Memory Error가 발생할 수 있습니다.여기에서는, 내가 그것을 잡고 나서 해상도를 낮추면 도움이 된다.
- '좋은'을 어떻게 정의하느냐에 따라 다르죠버그가 많은 웹 어플리케이션에서 실행하며 대부분의 경우 동작합니다(다행히 현재).
OutOfMemory
관련 없는 수정으로 인해 발생하지 않습니다.)단, 스레드가 여러 개 있는 경우 메모리 할당이 실패할 수 있습니다.따라서 어플리케이션에 따라서는 아직 10~90%가 고장날 가능성이 있습니다. - 제가 알기론, 무거운 스택을 풀면 너무 많은 참조가 무효가 되므로 메모리를 너무 많이 확보할 수 있습니다.
편집: 시험 edit edit edit edit edit edit edit edit edit edit edit edit 。예를 들어, 점진적으로 더 많은 메모리를 할당하는 함수를 재귀적으로 호출하는 프로그램을 작성합니다. ★★★★OutOfMemoryError
그 시점부터 의미 있게 계속할 수 있는지 알아보세요.제 경험에 따르면, 제 경우 Web Logic 서버에서 일어난 일이기 때문에 흑마법이 관련되어 있을 수 있습니다.
[Throwable]아래에서 무엇이든 잡을 수 있습니다.일반적으로 예외 서브클래스는 런타임 이외의 서브클래스만 잡아야 합니다.예외(많은 개발자가 런타임도 인식하지만)예외...하지만 언어 디자이너의 의도는 결코 아니었습니다.)
Out Of Memory Error가 검출되면 어떻게 하시겠습니까?VM의 메모리가 부족합니다.기본적으로 할 수 있는 일은 종료뿐입니다.메모리가 부족하다는 것을 알리기 위해 대화 상자를 열 수도 없습니다.메모리가 부족하다는 것은 메모리가 필요하기 때문입니다.
VM은 메모리가 실제로 부족할 때(실제로 모든 오류는 복구할 수 없는 상황을 나타내야 함) Out Of Memory Error를 발생시키며, 이 문제를 해결하기 위해 사용자가 할 수 있는 일이 없습니다.
해야 할 일은 메모리가 부족한 이유(NetBeans 등의 프로파일러 사용)를 찾아 메모리 누수가 없는지 확인하는 것입니다.메모리 누수가 없는 경우 VM에 할당하는 메모리를 늘립니다.
언급URL : https://stackoverflow.com/questions/2679330/catching-java-lang-outofmemoryerror
'source' 카테고리의 다른 글
인터페이스, 구현 또는 둘 다에 대해 코멘트하시겠습니까? (0) | 2022.09.03 |
---|---|
불필요한 스터빙 예외 해결 방법 (0) | 2022.09.03 |
다양한 64비트 데이터 모델과 비교하여 32비트(size_t)의 사이즈는 어떻게 됩니까? (0) | 2022.09.03 |
Closeable 구현 또는 AutoCloseable 구현 (0) | 2022.09.03 |
스프링 테스트에서 환경 변수 또는 시스템 속성을 설정하는 방법은 무엇입니까? (0) | 2022.09.03 |