일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
- python3
- mysql
- 자바
- HTTP
- ORM
- rabbitmq
- Spring
- django
- 파이썬
- 스프링
- 자료구조
- 보안
- node.js
- 스프링 부트
- BCI
- db
- JPA
- Spring Boot
- 장고
- bytecode
- Python
- 웹
- 개발
- 디자인 패턴
- 웹 개발
- 안드로이드
- java
- 파이썬3
- 데이터베이스
- 스프링부트
- Today
- Total
semtax의 개발 일지
자바 Uncaught Exception 캐치 하기 본문
개요
이번 포스팅에서는, 자바의 모든 예외(Exception)을 한번애 전부 캐치 할 수 있는 방법에 대해서 포스팅을 하도록 하겠다.
자바 예외 처리
자바에서는 보통 아래와 같이 try-catch 문을 이용해서 에러를 핸들링 할 수 있다.
public class ExampleClass {
public static void main(String[ ] args) {
try {
int[] numbers = {1, 2, 3};
System.out.println(numbers[10]);
} catch (Exception e) {
System.out.println("Exception is occured!");
}
}
}
또한, throws 를 이용해서 예외를 다른곳으로 전파 할 수도 있다.
(보통 해당 클래스를 호출한곳에서 예외를 처리하게 할때 많이 사용한다.)
class ThrowsExample
{
static void fun()
{
try
{
throw new NullPointerException("Null pointer reference error!");
}
catch(NullPointerException e)
{
System.out.println("Caught inside fun().");
throw e; // rethrowing the exception
}
}
public static void main(String args[])
{
try
{
fun();
}
catch(NullPointerException e)
{
System.out.println("Caught in main.");
}
}
}
하지만, 아래와 같이 어떠한 예외도 처리하지 않는 경우에는 어떻게 될까?
public class MainClass {
public static void main(String[] args) {
int[] arr = new int[10];
arr[12] = 10;
}
}
그떄는 아래와 같은 에러메시지가 발생한다.
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 12
at MainClass.main(MainClass.java:13)
신기한것은, 우리는 예외처리를 한 것이 추가한게 없는데도 불구하고 자바에서 위와 같이 예외가 발생했을때, 에러메시지들을 찍어주는 역할을 한다는 것이다.
그렇다면 자바에서는 위와 같이, 사용자가 어떠한 예외도 처리하지 않는 경우에 위와 같이 예외를 어떻게 처리할 수 있는 것일까?
한 번, 해당 방법에 대해서 알아보도록 하자.
Uncaught Exception Handler
정답은, 자바의 Thread 클래스에 있는 UncaughtExceptionHandler 라는 핸들러에 의해 기본적으로 등록된 핸들러에서 나머지 에러를 처리하게 된다.
따로 UncaughtExceptionHandler 를 설정해주지 않은 경우, 자바에서 기본적으로 정의된 UncaughtExceptionHandler 가 실행이 된다.
또한, 위의 DefaultUncaughtExceptionHandler 를 아래와 같이 직접 정의해서 사용 가능하다.
아래와 같이 정의해서 사용 할 수 있다.
public class DefaultExceptionHandler implements Thread.UncaughtExceptionHandler {
@Override
public void uncaughtException(Thread t, Throwable e) {
StackTraceElement[] stackTraceElements = t.getStackTrace();
StackTraceElement[] exceptionStackTraceElements = e.getStackTrace();
System.out.println("Thread Name : " + t.getName());
System.out.println("=========================================");
for(StackTraceElement element : stackTraceElements) {
System.out.println("class name : " + element.getClassName());
System.out.println("file name : " + element.getFileName());
System.out.println("method name : " + element.getMethodName());
System.out.println("line number : " + element.getLineNumber());
}
System.out.println("=========================================");
System.out.println("Exception Message : " + e.getMessage());
System.out.println("Exception Localized Message : " + e.getLocalizedMessage());
System.out.println("Exception Cause : " + e.getCause());
for(StackTraceElement element : exceptionStackTraceElements) {
System.out.println("=========================================");
System.out.println("exception class name : " + element.getClassName());
System.out.println("exception file name : " + element.getFileName());
System.out.println("exception method name : " + element.getMethodName());
System.out.println("exception line number : " + element.getLineNumber());
System.out.println("=========================================");
}
}
}
위의 UncaughtExpcetionHandler 를 통해, 해당 예외가 발생한 스레드의 전체 스택트레이스, 스레드 이름, 예외가 발생한 함수의 스택 트레이스, 에러메시지, 에러가 발생한 클래스이름, 메소드 이름, 파일 이름 등을 얻을 수 있다.
또한, 자바 디버깅 심볼 데이터가 살아있는 경우, 해당 에러가 발생한 라인 번호도 얻을 수 있다.
(만약 디버깅 심볼 데이터가 없는 경우 Unknown 이라고 뜬다.)
위에서 정의한 핸들러를 등록하는 방법은 아래와 같다.
Thread.setDefaultUncaughtExceptionHandler(new DefaultExceptionHandler());
아래와 같이 사용해보도록 하자.
public class MainClass {
public static void main(String[] args) throws InterruptedException{
Thread.setDefaultUncaughtExceptionHandler(new DefaultExceptionHandler());
AnotherTask task1 = new AnotherTask();
Thread t1 = new Thread(task1);
t1.start();
while(true) {
}
}
}
그러면 다음과 같은 메시지를 얻을 수 있다.
Thread Name : Thread-0
=========================================
class name : java.lang.Thread
file name : Thread.java
method name : getStackTrace
line number : 1559
class name : DefaultExceptionHandler
file name : DefaultExceptionHandler.java
method name : uncaughtException
line number : 6
class name : java.lang.ThreadGroup
file name : ThreadGroup.java
method name : uncaughtException
line number : 1057
class name : java.lang.ThreadGroup
file name : ThreadGroup.java
method name : uncaughtException
line number : 1052
class name : java.lang.Thread
file name : Thread.java
method name : dispatchUncaughtException
line number : 1959
=========================================
Exception Message : / by zero
Exception Localized Message : / by zero
Exception Cause : null
=========================================
exception class name : AnotherTask
exception file name : AnotherTask.java
exception method name : run
exception line number : 4
=========================================
=========================================
exception class name : java.lang.Thread
exception file name : Thread.java
exception method name : run
exception line number : 748
=========================================
활용
보통, Sentry와 같은 에러 트래킹 솔루션에서 위와 같은 방법을 사용해서 에러 트래킹을 수행한다.
'개발 > Java' 카테고리의 다른 글
디자인패턴 공부내용 정리 : 빌더 패턴 (0) | 2020.05.16 |
---|---|
스프링부트 에서 카프카 써서 메시지 주고 받아보기 (4) | 2020.05.16 |
스프링부트로 게시판 만들기 12(完) : API 문서 생성 자동화 (0) | 2020.05.02 |
스프링부트로 게시판 만들기 11 : 파일 업로드/다운로드 구현 (1) | 2020.05.02 |
스프링부트로 게시판 만들기 10 : 검색기능 추가 (0) | 2020.05.01 |