java.lang.Error를 언제 잡을까요?


답변:


101

일반적으로 결코.

그러나 때로는 특정 오류를 포착해야합니다.

프레임 워크와 같은 코드를 작성하는 경우 (타사 클래스로드), 잡는 것이 현명 할 수 있습니다. LinkageError (클래스 정의 없음, 만족스럽지 않은 링크, 호환되지 않는 클래스 변경).

나는 또한의 서브 클래스를 던지는 어리석은 써드 파티 코드를 보았습니다 Error.

그건 그렇고,에서 복구 할 수 없는지 잘 모르겠습니다 OutOfMemoryError.


3
DLL을로드하기 위해 정확히 수행해야했는데 제대로 구성되지 않으면 실패했습니다. 이 응용 프로그램의 경우 치명적인 오류가 아닙니다.
Mario Ortegón

7
예를 들어 큰 배열 목록을 생성 할 때 OutOfMemoryError를 포착하는 것이 때때로 의미가 있습니다.
SpaceTrucker 2013 년

3
@SpaceTrucker :이 접근 방식이 다중 스레드 응용 프로그램에서 잘 작동합니까, 아니면 다른 스레드의 작은 할당이 이로 인해 실패 할 위험이 있습니까? … 아마도 여러분의 어레이가 할당 될만큼 작았지만 다른 사람에게는 아무것도 남지 않은 경우에만 해당됩니다.
PJTraill

@PJTraill 나는 그것에 대해 잘 모르겠습니다. 실제 통계 샘플이 필요합니다. 그런 코드를 본 적이 있다고 생각했지만 어디에 있는지 기억이 나지 않습니다.
SpaceTrucker 2015-06-13

51

못. 응용 프로그램이 다음 코드 줄을 실행할 수 있는지 확신 할 수 없습니다. 를 받으면 어떤 일이든 안정적으로 할 수 있다는 보장OutOfMemoryError없습니다 . RuntimeException을 잡아 예외를 확인했지만 오류는 확인하지 않았습니다.

http://pmd.sourceforge.net/rules/strictexception.html


27
결코 말하지 마십시오. "assert false"를 수행하는 테스트 코드가 있습니다. 그런 다음 AssertionError를 포착하여 -ea 플래그가 설정되었는지 확인합니다. 그 외에는 ... 그래, 아마 절대 ;-)
Outlaw Programmer

3
작업자 스레드에 요청을 전달하는 서버 애플리케이션은 어떻습니까? 작업자 스레드에서 Throwable을 잡아서 오류를 잡아 내고 적어도 무엇이 잘못되었는지 기록하는 것은 말이되지 않을까요?
Leigh

11
절대로 ... 꼭 필요한 경우를 제외하고. 절대로 강력한 단어는 없으며 규칙에는 항상 예외가 있습니다. 프레임 워크를 구축하는 경우 로그 만 남기더라도 특정 오류를 포착하고 처리해야 할 가능성은 거의 없습니다.
Robin

타사 라이브러리 메소드에서 발생하는 NoSuchMethodError와 같은 오류는 어떻습니까?
ha9u63ar

@OutlawProgrammer 기록을 위해 동일한 테스트를 수행하는 다른 방법이 있습니다.boolean assertionsEnabled = false; assert assertionsEnabled = true;
shmosel

16

일반적으로 항상 java.lang.Error로그에 기록하거나 사용자에게 표시해야합니다. 저는 지원팀에서 일하며 프로그래머가 프로그램에서 무슨 일이 일어 났는지 말할 수 없다는 것을 매일 봅니다.

데몬 스레드가있는 경우 종료되는 것을 방지해야합니다. 다른 경우에는 응용 프로그램이 올바르게 작동합니다.

java.lang.Error최고 수준 에서만 잡을 수 있습니다.

오류 목록을 보면 대부분 처리 할 수 ​​있음을 알 수 있습니다. 예를 들어 a ZipError는 손상된 zip 파일을 읽을 때 발생합니다.

가장 일반적인 오류는 OutOfMemoryError및이며 NoClassDefFoundError, 대부분의 경우 런타임 문제입니다.

예를 들면 :

int length = Integer.parseInt(xyz);
byte[] buffer = new byte[length];

생성 할 수 OutOfMemoryError있지만 런타임 문제이며 프로그램을 종료 할 이유가 없습니다.

NoClassDefFoundError라이브러리가 없거나 다른 Java 버전으로 작업하는 경우 대부분 발생합니다. 프로그램의 선택적 부분 인 경우 프로그램을 종료해서는 안됩니다.

Throwable최상위 수준에서 포착 하고 유용한 오류 메시지를 생성하는 것이 좋은 생각 인 이유에 대한 더 많은 예를 제공 할 수 있습니다 .


나는 그것이 정말로 살아 있고 뭔가를하고 있다는 잘못된 구실을 줄 수있는 실패한 jvm에서 일부 에테르 유령으로 살아있을 가능성을 가지기 위해 적절한 경고로 데몬을 실패하는 것이 더 낫다고 생각합니다.
Andrew 노먼

OutOfMemoryError런타임 오류가 아닙니다. 애플리케이션이 복구 할 수 있다는 보장이 없습니다. 운이 좋으면 OOM을 가져올 수 new byte[largeNumber]있지만 할당이 OOM을 유발하기에 충분하지 않은 경우 다음 줄 또는 다음 스레드에서 트리거 될 수 있습니다. length신뢰할 수없는 입력 인 경우을 호출하기 전에 유효성을 검사해야 하므로 런타임 문제 new byte[]입니다.
김지영

NoClassDefFoundError컴파일 된 자바 코드가 클래스를 찾을 수 없을 때 호출되므로 어디서나 발생할 수 있습니다 . JDK가 잘못 구성되면 java.util.*클래스 사용 시도가 트리거 될 수 있으며 이에 대해 프로그래밍하는 것은 사실상 불가능합니다. 선택적으로 종속성을 포함하는 경우을 사용 ClassLoader하여 존재하는지 확인 해야합니다 ClassNotFoundException.
김지영

1
ZipError클래스가 포함 된 jar 파일이 손상된 zip 파일임을 나타냅니다. 이것은 매우 심각한 문제이며이 시점에서 실행되는 코드를 신뢰할 수 없으며 그로부터 "복구"를 시도하는 것은 무책임한 일입니다.
김지영

2
일반적으로, 그것은 잡을 도움이 될 수 있습니다 java.lang.Error또는 java.lang.Throwable최상위 수준과 그것으로 뭔가를 시도 - 오류 메시지를 기록 말한다. 그러나 그 시점에서 이것이 실행될 것이라는 보장은 없습니다. JVM이 OOMing 인 경우 로그를 시도하면 더 많은을 할당하여 String다른 OOM을 트리거 할 수 있습니다 .
김지영

15

다중 스레드 환경에서 가장 자주 포착하고 싶어합니다! 당신이 그것을 잡으면 그것을 기록하고 전체 응용 프로그램을 종료하십시오! 그렇게하지 않으면 중요한 부분을 수행 할 수있는 일부 스레드가 죽고 나머지 응용 프로그램은 모든 것이 정상이라고 생각합니다. 그 중에서 원하지 않는 상황이 많이 발생할 수 있습니다. 가장 작은 문제 중 하나는 다른 스레드가 하나의 스레드가 작동하지 않아 일부 예외를 던지기 시작하면 문제의 원인을 쉽게 찾을 수 없다는 것입니다.

예를 들어, 일반적으로 루프는 다음과 같아야합니다.

try {
   while (shouldRun()) {
       doSomething();
   }
}
catch (Throwable t) {
   log(t);
   stop();
   System.exit(1);
}

어떤 경우에도 다른 오류를 다르게 처리하기를 원할 것입니다. 예를 들어 OutOfMemoryError에서는 애플리케이션을 정기적으로 닫을 수 있고 (일부 메모리를 확보하고 계속할 수도 있음) 다른 일부에서는 수행 할 수있는 작업이 많지 않습니다.


1
프로그램이 정의되지 않은 상태에 있기 때문에 즉시 존재하는 것보다 잡아서 OutOfMemoryError 계속 하는 것은 현명하지 않습니다 .
Raedwald 2015

1
호출 시스템, throwable을 잡을 때 종료하면 해당 응용 프로그램뿐만 아니라 JVM에서 실행중인 모든 것을 종료하는 의도하지 않은 결과가 발생합니다. 일반적으로 다른 웹 애플리케이션과 함께 앱 서버에서 호스팅 될 수있는 웹 애플리케이션에는 좋지 않습니다 (앱 서버 자체에 영향을 미칠 수 있음).
Andrew Norman

9

아주 드물게.

스레드가 죽는 이유가있는 메시지를 발행하기 위해 스레드의 최상위 수준에서만 말하고 싶습니다.

이런 종류의 작업을 수행하는 프레임 워크에 있다면 프레임 워크에 맡기십시오.


6

거의 없다. 오류는 응용 프로그램이 일반적으로 수행 할 수없는 문제로 설계되었습니다. 유일한 예외는 오류 표시를 처리하는 것이지만 오류에 따라 계획대로 진행되지 않을 수도 있습니다.


6

Error발생하지 않아야하는 비정상적인 상태를 나타내 므로 일반적으로 잡히면 안됩니다. .

Error클래스에 대한 Java API 사양에서 :

An ErrorThrowable 합리적인 응용 프로그램이 포착하려고하지 않아야하는 심각한 문제를 나타내는 의 하위 클래스입니다 . 이러한 오류는 대부분 비정상 상태입니다. [...]

메서드는 throws 절에서 메서드 실행 중에 throw 될 수 있지만 포착되지 않은 Error의 하위 클래스를 선언 할 필요가 없습니다. 이러한 오류는 발생해서는 안되는 비정상적인 조건이기 때문입니다.

사양에서 언급했듯이 Error는 가능성이있는 상황에서만 발생하며, Error발생시 응용 프로그램이 수행 할 수있는 작업이 거의 없으며 일부 상황에서는 Java Virtual Machine 자체가 불안정한 상태 (예 :VirtualMachineError )

an Error은 절에 Throwable의해 잡힐 수 있음을 의미 하는 하위 클래스 try-catch이지만 응용 프로그램이 비정상 상태에있을 때 실제로 필요하지는 않습니다.Error JVM에 의해 발생합니다.

Section 11.5 The Exception Hierarchy of the Java Language Specification, 2nd Edition 에도이 주제에 대한 짧은 섹션이 있습니다.


6

새로운 단위 테스트 프레임 워크를 만드는 데 충분히 미쳤다면 테스트 실행기는 테스트 케이스에서 발생하는 java.lang.AssertionError를 잡아야 할 것입니다.

그렇지 않으면 다른 답변을 참조하십시오.


5

그리고 오류를 발견하면 다시 던져야 하는 몇 가지 다른 경우가 있습니다 . 예를 들어 ThreadDeath 는 절대 잡히지 않아야합니다. 포함 된 환경 (예 : 응용 프로그램 서버)에서 잡으면 큰 문제가 발생할 수 있습니다.

응용 프로그램은 비동기 적으로 종료 된 후 정리해야하는 경우에만이 클래스의 인스턴스를 포착해야합니다. ThreadDeath가 메서드에 의해 잡히면 스레드가 실제로 죽도록 다시 throw되는 것이 중요합니다.


2
단순히 s를 잡지 않기 때문에 실제로 문제가 되지 않습니다Error .
Bombe

4

아주 드물게.

나는 아주 특정한 한 가지 알려진 경우에만 그것을했다. 예를 들어, 두 개의 독립 ClassLoader가 동일한 DLL을로드하는 경우 java.lang.UnsatisfiedLinkError가 발생할 수 있습니다 . (JAR를 공유 클래스 로더로 이동해야한다는 데 동의합니다)

그러나 가장 일반적인 경우는 사용자가 불만을 제기했을 때 무슨 일이 일어 났는지 알기 위해 로깅이 필요하다는 것입니다. 사용자에게 메시지 나 팝업이 표시되기를 원합니다.

C / C ++의 프로그래머조차도 오류를 표시하고 종료하기 전에 사람들이 이해하지 못하는 것을 알려줍니다 (예 : 메모리 오류).


3

Android 애플리케이션에서 java.lang.VerifyError를 포착하고 있습니다 . 내가 사용중인 라이브러리는 이전 버전의 OS가 설치된 장치에서 작동하지 않으며 라이브러리 코드에서 이러한 오류가 발생합니다. 물론 런타임에 OS 버전을 확인하여 오류를 피할 수 있지만 :

  • 지원되는 가장 오래된 SDK는 향후 특정 라이브러리에 대해 변경 될 수 있습니다.
  • try-catch 오류 블록은 더 큰 폴백 메커니즘의 일부입니다. 일부 특정 장치는 라이브러리를 지원해야하지만 예외를 발생시킵니다. 대체 솔루션을 사용하기 위해 VerifyError 및 모든 예외를 포착합니다.

3

테스트 환경에서 java.lang.AssertionError를 잡는 것은 매우 편리합니다 ...


추가하려는 가치는 무엇입니까?
lpapp 2013

테스트 스위트가 중단되지 값 추가
Jono

2

이상적으로는 오류를 처리 / 캐치하지 않아야합니다. 그러나 프레임 워크 나 응용 프로그램의 요구 사항에 따라해야 할 경우가있을 수 있습니다. 더 많은 메모리를 소비 하는 DOM 파서 를 구현하는 XML 파서 데몬이 있다고 가정 해 보겠습니다 . Parser 쓰레드가 OutOfMemoryError를 받았을 때 죽지 말아야한다는 요구 사항이 있다면 , 대신 그것을 처리하고 애플리케이션 / 프레임 워크 관리자에게 메시지 / 메일을 보내야합니다.


1

이상적으로는 비정상적인 조건이므로 Java 애플리케이션에서 오류를 포착해서는 안됩니다. 응용 프로그램이 비정상적인 상태에 있고 캐싱이 발생하거나 심각한 잘못된 결과를 초래할 수 있습니다.


1

어설 션이 만들어 졌는지 확인하는 단위 테스트 내에서 오류를 포착하는 것이 적절할 수 있습니다. 누군가 어설 션을 비활성화하거나 그렇지 않으면 알고 싶은 어설 션을 삭제하는 경우


1

JVM이 더 이상 예상대로 작동하지 않거나 직전에있는 경우 오류가 발생합니다. 오류를 발견하면 catch 블록이 실행된다는 보장이 없으며 끝까지 실행될 것이라는 보장도 없습니다.

또한 실행중인 컴퓨터, 현재 메모리 상태에 따라 달라 지므로 최선을 다해 테스트하고 시도 할 방법이 없습니다. 당신은 끔찍한 결과를 얻을 것입니다.

또한 코드의 가독성도 저하됩니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.