스택 추적을 잃지 않고 Java에서 예외를 다시 발생


417

C #에서는 throw;명령문을 사용 하여 스택 추적을 유지하면서 예외를 다시 발생 시킬 수 있습니다 .

try
{
   ...
}
catch (Exception e)
{
   if (e is FooException)
     throw;
}

Java에 이와 같은 것이 있습니까 ( 원래 스택 추적을 잃지 않습니다 )?


4
왜 원래 스택 트레이스가 느슨하다고 생각합니까? 새로운 SomeOtherException을 던지고 생성자 또는 initCause ()에 근본 원인을 할당하는 것을 잊었을 때 그것을 잃을 수있는 유일한 방법입니다.
akarnokd

4
이것이 코드가 .Net에서 동작하는 방식이라고 생각하지만 더 이상 긍정적이지 않습니다. 어딘가에서 찾거나 작은 테스트를 실행하는 것이 좋습니다.
ripper234

11
Throwable던지더라도 수정되지 않습니다. 스택 추적을 업데이트하려면을 호출해야합니다 fillInStackTrace(). 편리하게이 메소드는의 생성자에서 호출됩니다 Throwable.
Robert

50
C #에서 예, throw e;스택 추적이 손실됩니다. 그러나 Java에서는 아닙니다.
Tim Goodman

Java 7의 예외에 대한 Oracle의 일부 문서 : 여러 예외 유형
포착

답변:


560
catch (WhateverException e) {
    throw e;
}

단순히 잡은 예외를 다시 던질 것입니다 (분명히 주변 메소드는 서명 등을 통해 이것을 허용해야합니다). 예외는 원래 스택 추적을 유지합니다.


4
안녕하세요, InterruptedException e는 throw e 라인을 추가 할 때 처리되지 않은 예외 메시지를 제공합니다. 더 넓은 예외 e로 바꾸면 그렇지 않습니다. 이 작업을 어떻게 올바르게 수행해야합니까?
James P.

1
@James, 방금 함수 선언에 "throws XxxException"을 추가하면 메시지가 사라지는 것을 관찰했습니다.
shiouming

2
이러한 재 투입을위한 Java 7 컴파일러는 더 무해합니다. 이제는 메소드를 포함하는 특정 "throws"예외와 함께 잘 작동합니다.
Waldemar Wosiński

193
@James 만약 당신 catch(Exception e) { throw e; }이 처리되지 않을 것입니다. 당신 catch(InterruptedException ie) { throw ie; }이 처리됩니다. 경험상, catch(Exception e)이건 포켓몬이 아니며, 우리는 모두를 잡기를 원하지 않습니다!
corsiKa

3
@corsiKa "모두 잡기"를 원하지 않는다는 것이 반드시 사실은 아니며, 다른 사용 사례 일뿐입니다. 적어도 RuntimeException을 잡아서 기록하지 않으면 최상위 루프 또는 이벤트 처리기 (예 : 스레드 실행 내부)가있는 경우 예외를 완전히 놓치지 않고 중요한 루프에서 자동으로 중단됩니다. 종종 일회성 실패입니다. 추가 코드가 무엇을하거나 던질 지 모르는 플러그인 기능에도 정말 좋습니다. 이러한 잡기와 같은 하향식 용도의 경우 예외는 종종 좋은 아이디어 일뿐만 아니라 모범 사례입니다.
Bill K

82

내가 선호하는:

try
{
    ...
}
catch (FooException fe){
   throw fe;
}
catch (Exception e)
{
    // Note: don't catch all exceptions like this unless you know what you
    // are doing.
    ...
}

6
Java에서 일반적인 예외 및 확인 이외의 특정 예외를 포착하는 것이 확실합니다. +1
amischiefr

8
당신이하고있는 일을 알지 못한다면 평범한 "예외"를 포착해서는 안되기 때문에 -1.
Stroboskop

19
@Stroboskop : 사실이지만 대답하려면 질문과 동일한 (유사한) 코드를 사용하는 것이 가장 좋습니다!
user85421

14
때로는 모든 예외를 잡는 것이 좋습니다. 테스트 사례를 작성하는 경우 등 또는 로깅 목적으로. 또는 잡히지 않는 곳에서는 충돌이 발생합니다.
John Henckel

1
@JohnHenckel 및 기타 : 유효한 점수가 표시됩니다. 대부분의 경우 (모두는 아님) 잡기 Exception가 일반적으로 옳지 않다는 것을 분명히하기 위해 질문을 업데이트 했습니다 .
Per Lundberg

74

또한 예외를 다른 예외로 랩핑하고 원인 매개 변수로 Exception을 Throwable로 전달하여 원래 스택 추적을 유지할 수 있습니다.

try
{
   ...
}
catch (Exception e)
{
     throw new YourOwnException(e);
}

8
또한throw new YourOwnException("Error while trying to ....", e);
Julien

이것은 내가 찾던 것, 특히 당신이 당신의 자신의 메시지를 전달할 수있는 첫 번째 코멘트의 버전
Csaba

이것은 오류 메시지를 올바르게 표시하지만 스택 추적은 오류 행을 예외를 발생시킨 원래 행이 아닌 'throw new ....... (e)'가있는 행으로 표시합니다.
Ashburn RK

22

Java에서는 거의 동일합니다.

try
{
   ...
}
catch (Exception e)
{
   if (e instanceof FooException)
     throw e;
}

5
새 예외 객체를 인스턴스화하지 않는 한 스택 추적은 동일하게 유지됩니다.
Mnementh

28
FooException에 대한 특정 캐치를 추가합니다
dfa

3
이 특정 경우에 동의하지만 특정 캐치를 추가하는 것이 올바른 선택이 아닐 수 있습니다. 모든 예외에 대한 공통 코드가 있고 특정 예외에 대해 다시 던질 것이라고 상상해보십시오.
송아지

1
@MarkusLausberg 그러나 마침내 예외를 잡을 수는 없습니다.
Robert

예, 그러나 이것은 질문이 아닙니다.
Markus Lausberg

14

Java에서는 잡은 예외를 그냥 던지기 throw e보다는 던져 버립니다 throw. Java는 스택 추적을 유지 관리합니다.


6

이 같은

try 
{
  ...
}
catch (FooException e) 
{
  throw e;
}
catch (Exception e)
{
  ...
}

5
public int read(byte[] a) throws IOException {
    try {
        return in.read(a);
    } catch (final Throwable t) {
        /* can do something here, like  in=null;  */
        throw t;
    }
}

이것은 메소드가를 던지는 구체적인 예 IOException입니다. final수단 t에만 try 블록에서 던진 예외를 보유 할 수 있습니다. 추가 자료는 여기여기 에서 찾을 수 있습니다 .



3

잡은 excetion을 다른 예외로 랩핑하거나 (더 많은 정보를 제공하기 위해) 잡은 excetion을 다시 던지면 스택 추적이 보존됩니다.

try{ ... }catch (FooException e){ throw new BarException("Some usefull info", e); }


2

내 코드에서 잠재적으로 다시 던지기를 원하는 여러 가지 예외가 발생할 가능성이 비슷한 상황이 발생했습니다. Eclipse가 처리되지 않은 throw e;예외로 이어진다 고 말했기 때문에 위에서 설명한 솔루션 이 효과가 없었습니다.

try
{
...
} catch (NoSuchMethodException | SecurityException | IllegalAccessException e) {                    
    throw new RuntimeException(e.getClass().getName() + ": " + e.getMessage() + "\n" + e.getStackTrace().toString());
}

나를 위해 일했다 .... :)

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