IT

exception.printStackTrace ()가 왜 나쁜 습관으로 넘어가나요?

lottoking 2020. 7. 16. 07:57
반응형

exception.printStackTrace ()가 왜 나쁜 습관으로 넘어가나요?


많이재료를 밖으로 예외의 스택 트레이스를 인쇄하는 [해석] 잘못된 방법입니다 제안합니다.

예를 들어 Checkstyle의 RegexpSingleline 확인에서 :

이 검사는 [...] ex.printStacktrace () 호출과 같은 일반적인 나쁜 습관을 찾는 데 사용할 수 있습니다.

그러나 스택 추적이 예외의 원인을 추적하는 데 매우 유용하기 때문에 유효한 이유를 제공하는 곳을 찾기 위해 고심하고 있습니다. 내가 알고있는 것 :

  1. 최종 사용자에게 스택 추적이 표시되지 않습니다. (사용자 경험 및 보안 목적으로)

  2. 스택 추적 생성은 비싼 프로세스입니다 (대부분의 '예외적'환경에서는 문제가 없습니다)

  3. 많은 로깅 프레임 워크가 스택 추적을 인쇄합니다 (우리는 말할 수 없습니다).

  4. 스택 추적을 인쇄해서 오류가 처리되지 않습니다. 다른 정보 로깅 및 예외 처리와 함께합니다.

코드에 스택 추적을 인쇄하지 않는 다른 이유는 무엇입니까?


Throwable.printStackTrace()스택 추적을 System.errPrintStream에 씁니다 . System.errJVM 프로세스 스트림 및 기본 표준 "오류"출력 스트림은 다음을 통해 리디렉션 될 수 있습니다.

  • 에서 대상을 변경하는 호출 .System.setErr()System.err
  • 또는 프로세스의 오류 출력 스트림을 리디렉션하여. 오류 출력 스트림이 파일 / 장치로 리디렉션 될 수 있습니다.
    • 직원이 내용을 무시할 수있는 경우
    • 파일 / 장치는 로그 회전이 불가능하여 파일 / 장치의 기존 내용을 아카이브하기 전에 열린 파일 / 장치 핸들을 닫으려면 프로세스를 다시 시작해야 할 것으로 추정합니다.
    • 또는 파일 / 장치는의 경우와 같이 실제로 기록 된 모든 데이터를 버립니다 /dev/null.

많은 언급 된 것처럼, 호출 Throwable.printStackTrace()은 유효한 (좋은 / 큰 아닌) 예외 처리 동작을 구성합니다.

  • System.err애플리케이션 수명 기간 동안 재 할당 되지 않은 경우 ,
  • 응용 프로그램이 실행되는 동안 로그 회전이 필요하지 않은 경우
  • 응용 프로그램의 허용 / 설계 로깅 방법은 System.err(및 JVM의 표준 오류 출력 스트림)에 기록하는 것입니다.

대부분의 경우 위의 조건이 없습니다. JVM에서 실행되는 다른 코드를 인식하지 않는 로그 파일의 크기 나 실행의 작동 기간을 예측할 수 있습니다. 로그 파일 작성을 실행하는 것이 좋습니다. 하지만 선택적인 기능).

마지막으로,의 출력은 Throwable.printStackTrace()다른 경우에 등장 질 것입니다 System.err( System.out둘 다 같은 파일 / 장치로 된 리디렉션에도 ). 이는 예외 관련 데이터를 쉽게 구문 분석 할 수 없기 때문에 처리하는 성가심 (단일해야 할 앱의 경우)입니다. 다수의 다수의 응용 프로그램은 Throwable.printStackTrace() 많은 것들이 생성 할 수있는 많은 혼란스러운 로그를 생성 합니다.

System.err여러 행사 Throwable.printStackTrace()가 동시에 호출 될 때 스택 추적 쓰기 동기화하는 동기화 . 이 문제를 해결하기 위해 코드와 관련된 모니터에서 System.err(및 System.out대상 파일 / 장치가 동일한 경우) 코드를 동기화해야 로그 파일 상태를 유지하는 데 비용이 많이 들었습니다. 예를 들어, ConsoleHandlerStreamHandler클래스는 제공되는 로깅 기능에서 콘솔에 로그 레코드를 추가해야합니다 java.util.logging. 로그 레코드를 게시하는 실제 작업이 동기화됩니다. 로그 레코드를 게시하려는 모든 레코드는 해당 로그 레코드와 관련된 모니터의 잠금을해야합니다. StreamHandler예. System.out/를 사용하여 인터리브되지 않은 로그 레코드를 System.err보장하고 메시지를 보장 할 수있는 방식으로 게시해야합니다.

위의 모든 사항과 Throwable.printStackTrace()유용한 매우 많은 시나리오를 고려할 때 종종 호출하는 것이 나쁜 습관임을 알 수 있습니다.


이전 함께 단락 중 하나에서 인수를 확장하면 Throwable.printStackTrace콘솔에 쓰는 로거와 사용하는 것도 좋지 . 이는 동기화하는 반면 애플리케이션이 인터리브 된 로그 레코드를 사용하는 경우 다른 모니터에서 동기화하는 이유 때문입니다. 응용 프로그램에서 동일한 대상에 쓰는 두 개의 서로 다른 로거를 사용할 때 인수가 유효합니다.


여러 문제를 만지고 있습니다.

1) 스택 추적은 최종 사용자에게 추가합니다 (사용자 경험 및 보안 목적으로)

예, 최종 사용자의 문제를 진단 할 수는 없지만 최종 사용자는 다음 두 가지 버전이 없습니다.

  • 모든 것은 매우 모호하고 읽을 수 있습니다.
  • 최종 사용자에게 스택 추적을 표시하면 강력한 보안 위험이 있습니다. 내가 틀렸다면 PHP를 수정 추적에 .PHP는 실제로 스택 추적에 함수 변수를 출력합니다-훌륭하지만 매우 위험합니다-데이터베이스에 연결하는 동안 예외가 발생하면 스택 추적에 무엇이 있습니까?

2) 스택 트레이스를 많이 사용하는 프로세스입니다 (그러나 대부분의 '예외')

스택 추적 생성은 예외가 생성 / 발생 될 때 발생합니다 (예외가 발생하면 가격이 함께 제공됨). 실제로 Throwable#fillInStackTrace()user-정의 예외를 무시 하여 간단한 GOTO만큼 저렴하게 문 예외를 효과적으로 처리 할 수 있습니다 .

3) 많은 로깅 프레임 워크가 스택 추적을 인쇄합니다 (우리는 쉽게 사용할 수 없습니다)

아주 좋은 지적입니다. 여기서 주요 문제는 프레임 워크가 예외를 기록하는 경우에는 사용하지 않습니다 (그렇지 않은 경우 확인하지 않습니다!) 예외를 로그 요청에 직접 확인 Logback 또는 Log4J 와 같은 로깅 프레임 워크를 하여 원시 콘솔에서 확인합니다. 제어하기가 매우 어렵 기 때문입니다.

로깅 프레임 워크를 사용하면 스택 추적을 파일, 콘솔로 쉽게 리디렉션하거나 지정된 전자 메일 주소로 보낼 수도 있습니다. 하드 코드 printStackTrace()사용하면 함께 살아야합니다 sysout.

4) 스택 추적 인쇄는 오류 처리를 구성하지 않습니다. 다른 정보 로깅 및 예외 처리와 함께합니다.

다시 한 번 : SQLException로깅 프레임 워크를 사용하여 전체 스택 추적으로 기록하고 " 미안합니다. 현재 요청을 처리 할 수 ​​있습니다 . 사용자가 그 이유에 관심이 얼마나 생각하십니까? StackOverflow 오류 화면을 보 많이? 유머러스하지만 매우 세부 사항을 밝히지 않습니다 . 그러나 사용자에게 문제를 조사 할 수 있습니다.

그는 그러나 합니다 즉시 전화하고 문제를 진단 할 수 있어야합니다. 따라서 적절한 예외적 로깅이 필요합니다.


정리하려면 : 항상 예외를 기록 하되 (가급적이면 로깅 프레임 워크 사용) 예외 를 최종 사용자에게 노출하지 마십시오. GUI의 오류 메시지에 대해 신중하게 생각하고 개발 모드에서만 스택 추적을 표시하십시오.


첫 번째로 printStackTrace () 는 예외가 자체적으로 생성 될 때 스택 추적이 채워지기 때문에 언급 한대로 비용이 많이 들지 않습니다.

아이디어는 로깅을 제어 할 수 있도록 로거 프레임 워크를 통해 로그로 이동하는 모든 것을 전달하는 것입니다. 따라서 printStackTrace를 사용하는 대신 다음과 같은 것을 사용하십시오.Logger.log(msg, exception);


나쁜 관행을 구성하지 않습니다 자체의 예외의 스택 트레이스를 인쇄하지만, 유일한 예외가 발생했을 때 스테이시 추적을 인쇄하는 것은 아마 여기에 문제 - 종종 그냥 스택 추적을 인쇄하는 것만으로는 충분하지 않습니다.

또한 catch블록 에서 수행되는 모든 작업이 .NET Framework 인 경우 적절한 예외 처리가 수행되지 않는다고 의심하는 경향 이 있습니다 e.printStackTrace. 부적절한 처리는 기껏해야 문제가 무시되고 최악의 경우 정의되지 않거나 예상치 못한 상태에서 계속 실행되는 프로그램을 의미 할 수 있습니다.

다음 예를 살펴 보겠습니다.

try {
  initializeState();

} catch (TheSkyIsFallingEndOfTheWorldException e) {
  e.printStackTrace();
}

continueProcessingAssumingThatTheStateIsCorrect();

여기서는 초기화가 수행되어야하는 일부 처리를 계속하기 전에 초기화 처리를 수행하려고합니다.

위의 코드에서 예외가 포착되고 적절하게 처리되어 프로그램 continueProcessingAssumingThatTheStateIsCorrect이 문제를 일으킬 수 있는 방법으로 진행되는 것을 방지해야합니다 .

대부분의 경우 e.printStackTrace()는 일부 예외가 삼켜지고 모든 문제가 발생하지 않는 것처럼 처리가 진행될 수 있음을 나타냅니다.

이것이 왜 문제가 되었습니까?

아마도 잘못된 예외 처리가 더 널리 퍼진 가장 큰 이유 중 하나는 Eclipse와 같은 IDE e.printStackTrace가 예외 처리를 위해 수행 할 코드를 자동 생성하는 방법 때문일 것입니다 .

try {
  Thread.sleep(1000);
} catch (InterruptedException e) {
  // TODO Auto-generated catch block
  e.printStackTrace();
}

(위는 try-catch이클립스가 InterruptedException던진 을 처리하기 위해 실제 자동 생성 된 것 Thread.sleep입니다.)

대부분의 응용 프로그램에서 스택 추적을 표준 오류로 인쇄하는 것만으로는 충분하지 않을 수 있습니다. 부적절한 예외 처리는 많은 경우 응용 프로그램이 예상치 못한 상태에서 실행되고 예기치 않은 정의되지 않은 동작으로 이어질 수 있습니다.


나는 당신의 이유 목록이 꽤 포괄적이라고 생각합니다.

내가 한 번 이상 만난 특히 나쁜 예는 다음과 같습니다.

    try {
      // do stuff
    } catch (Exception e) {
        e.printStackTrace(); // and swallow the exception
    }

위 코드의 문제는 처리가 전적으로printStackTrace 호출 로 구성된다는 입니다 . 예외가 실제로 제대로 처리되지 않거나 이스케이프가 허용되지 않습니다.

반면에 원칙적으로 코드에 예기치 않은 예외가있을 때마다 항상 스택 추적을 기록합니다. 수년 동안이 정책을 통해 디버깅 시간을 많이 절약 할 수있었습니다.

마지막으로, 가벼운 메모에서 하나님의 완벽한 예외 입니다.


printStackTrace()콘솔에 인쇄합니다. 프로덕션 환경에서는 아무도 그것을 보지 않습니다. Suraj가 정확합니다.이 정보를 로거에 전달해야합니다.


서버 애플리케이션에서 stacktrace는 stdout / stderr 파일을 날려 버립니다. 일반적으로 컨텍스트와 타임 스탬프 등이 없기 때문에 점점 더 커지고 쓸모없는 데이터로 채워질 수 있습니다.

예 : tomcat을 컨테이너로 사용할 때 catalina.out


PrintStackTrace ()에 대해 '잘못된'것이 있기 때문에 나쁜 습관이 아니라 '코드 냄새'이기 때문입니다. 누군가 예외를 제대로 처리하지 못했기 때문에 대부분의 경우 PrintStackTrace () 호출이 있습니다. 적절한 방식으로 예외를 처리하면 일반적으로 StackTrace에 대해 더 이상 신경 쓰지 않습니다.

또한 stderr에 스택 추적을 표시하는 것은 일반적으로 stderr가 아무데도 가지 않기 때문에 프로덕션이 아닌 디버깅 할 때만 유용합니다. 로깅하는 것이 더 합리적입니다. 그러나 PrintStackTrace ()를 예외 로깅으로 바꾸는 것만으로도 여전히 실패한 응용 프로그램이 남지만 아무 일도 일어나지 않은 것처럼 계속 실행됩니다.


일부 사람들이 이미 여기에서 언급했듯이 문제는 블록 e.printStackTrace()에서 호출하는 경우 예외 삼키는 것입니다 catch. 스레드 실행을 중지하지 않고 정상 상태 에서처럼 try 블록 이후에 계속됩니다.

그 대신 예외에서 복구 (복구 가능한 경우)를 시도하거나를 throw RuntimeException하거나 자동 충돌 (예 : 부적절한 로거 구성으로 인한)을 방지하기 위해 호출자에게 예외를 버블 링해야합니다.

참고 URL : https://stackoverflow.com/questions/7469316/why-is-exception-printstacktrace-considered-bad-practice

반응형