java는 오류가 발생하거나 발생할 여지가 있는 여러상황에 대한 예외를 만들어두었다.
우리에게 익숙한 IllegalArgumentException을 비롯해 원인을 찾기 힘든 NullPointerException도 있다. 또한, 파일 처리를 하다 보면 발생하기도 하는 IOException도 있다.
이번 포스팅에서 이런 예외에 대해 알아보자.
예외를 알아보기 위해서는 우선 오류와 예외를 구분할 필요가 있다.
✔️ 오류(Error)
오류(Error)는 시스템이 종료되어야 할 수준의 상황과 같이 수습할 수 없는 심각한 문제를 의미한다. 개발자가 미리 예측하여 방지할 수 밖에 없다.
✔️ 예외(Exception)
예외(Exception)는 개발자가 구현한 로직에서 발생한 실수나 사용자의 영향에 의해 발생한다. 오류와 달리 개발자가 미리 예측하여 방지할 수 있기에 상황에 맞는 예외처리(Exception Handle)를 해야 한다.
예외가 발생하면 프로그램이 종료가 된다는것은 에러와 동일하지만 예외는 예외처리(Exception Handling)을 통해 프로그램을 종료 되지 않고 정상적으로 작동되게 만들어줄 수 있다.
자바에서 예외처리는 Try Catch문을 통해 해줄 수 있다.
오류와 예외 모두 자바의 최상위 클래스인 Object를 상속받는다. 그리고 그 사이에는 Throwable이라는 클래스와 상속관계가 있다.
이 클래스에 대한 공식문서를 읽어보면 이 클래스의 객체에 오류나 예외에 대한 메시지를 담는다는 이야기가 나온다. 그리고 예외가 연결될 때(chained exception) 연결된 예외의 정보들을 기록하기도 한다고 한다.
이 Throwable 객체가 가진 정보와 할 수 있는 행위는 getMessage()
와 printStackTrace()
라는 메서드로 구현되어 있는데, 당연히 이를 상속받은 Error와 Exception에서 두 메서드를 사용한다.
✔️ StackOverflowError
: 응용 프로그램이 너무 많이 반복되어 StackOverflow가 발생할 때 던져지는 오류이다.
✔️ OutOfMemoryError
: JVM이 할당된 메모리의 부족으로 더 이상 객체를 할당할 수 없을 때 던져지는 오류이다.
- Garbage Collector에 의해 추가적인 메모리가 확보되지 못하는 상황일 때
- heap 사이즈 부족
- 너무 많은 class를 로드할 때
- 가용가능한 swap이 없을 때
- 큰 메모리의 native메서드가 호출될 때
이를 해결하기 위해, dump파일분석, jvm 옵션 수정 등이 있다.
앞서 말했듯 개발자가 미리 오류를 대처하기는 힘들다.
다만 StackOverflowError를 피하기 위해서 재귀를 사용할 때에 조심하거나 가시적인 loop를 사용하는 간접적인 예방이 가능하다.
또한 OutOfMemoryError를 피하기 위해 새는 메모리를 차단하거나 heap의 크기를 늘려주는 방법을 사용할 수도 있다.
예외는 개발자가 구현한 로직에서 발생하며 다른 방식으로 처리가능한 것들로, JVM은 정상 동작한다.
try-catch로 감싸거나 throw로 던져서 예외처리.
Runtime Exception
❗️ Checked Exception과 UncheckedException의 가장 명확한 구분 기준
: '꼭 처리를 해야 하는가'
✔️ ArithmeticException
: 정수를 0으로 나눌경우 발생
✔️⭐️ ArrayIndexOutOfBoundsException
: 배열의 범위를 벗어난 index를 접근할 시 발생ex) 길이가 3인
int[]arr = new int[3]
배열을 선언했다면,
0 ~ 2까지의 index만 사용할 수 있다. 하지만 이 배열의 index가 -1이나 3을 참조하는 순간 이 예외가 발생한다.
✔️⭐️⭐️ ClassCastException
: 변화할 수 없는 타입으로 객체를 반환 시 발생타입 변환은 상위클래스와 하위클래스간에 발생하고 구현 클래스와 인터페이스간에도 발생한다. 이런 관계가 아니면 클래스는 다른 클래스로 타입을 변환할 수 없다. 하지만 이 규칙을 무시하고 억지로 타입을 변환시킬 경우 발생하는 예외이다.
✔️⭐️⭐️⭐️ NullPointException
: 존재하지 않는 레퍼런스를 참조할 때 발생Java 프로그램에서 가장 빈번하게 발생하는 익셉션으로, 객체 참조가 없는 상태, 즉 null값을 갖는 참조변수로 객체 접근 연산자인 토드(.)를 사용했을 때 발생한다.
객체가 없는 상태에서 객체를 사용하려 했으니 예외가 발생하는 것.
✔️ IllegalArgumentException
: 잘못된 인자를 전달할 때 발생
✔️ IllegalStateException
: 객체의 상태가 메서드 호출에는 부적절한 경우에 발생
✔️ IOException
: 입출력 동작 실패 또는 인터럽트 시 발생
✔️ OutOfMemoryException
: 메모리가 부족한 경우 발생
✔️⭐️⭐️ NumberFormatException
: 문자열이 나타내는 숫자와 일치하지 않는 타입의 숫자로 변환시 발생개발을 하다보면 문자열로 되어있는 데이터를 숫자타입으로 변경하는 경우가 자주 발생하는데 숫자타입으로 변경할 수 없는 문자를 치환시키려고 하면 발생하는 예외이다.
✔️ CurrentModificationException
: 금지된 곳에서 객체를 동시에 수정하는 것이 감지될 경우 발생
✔️ UnsupportedOperationException
: 객체가 메서드를 지원하지 않는 경우 발생
Java에서 모든 예외가 발생하면 (XXX)Exception 객체를 생성한다.
예외를 처리하는 방법에는 크게 2가지가 있다.
try-catch
를 이용해서 예외에 대한 최종적인 책임을 지고 처리하는 방식throws Exception
을 이용해서 발생한 예외의 책임을 호출하는 쪽이 책임지도록 하는 방식 (주로 호출하는 쪽에 예외를 보고할 때 사용함)References
: https://toneyparky.tistory.com/40
: https://gyoogle.dev/blog/computer-language/Java/Error%20&%20Exception.html
: https://coding-factory.tistory.com/280