본문 바로가기
우아한테크코스 4기/레벨1

[Java] Java 예외처리와 StackOverFlow

by 나는후니 2022. 2. 21.

인테리어 커머스 플랫폼 인턴 면접을 보며 "StackOverFlow는 왜 발생하나요?" 라는 질문을 받았습니다.

저는 정말 단순하게 메모리가 초과했기 때문입니다. 라고 답변했으나 아마 이는 썩 만족스럽지 못한 대답이었을 것입니다.

 

오늘은 그날의 기억을 되돌리며 StackOverFlow라는 에러를 알아보고 이어서 Java가 어떻게 예외를 처리하는지 살펴보고자 합니다.

StackOverFlow

StackOverFlow는 VM에서 런타임 시점에 발생시키는 에러로 application이 너무 깊이 재귀를 할 때 발생하는 에러입니다.

아니 그런데 왜 이름이 RecurseTooDeepError 이런게 아닌가요?

이렇게 이름이 생긴 이유는 Java의 메모리 구조를 통해 유추해 볼 수 있습니다.

Java에서 인자지역변수는 stack 메모리에 할당됩니다. (물론 참조 타입의 값은 heap 메모리에 존재하겠죠?)

참고 :
이 때 stack 메모리는 저장 공간의 상단부터 아래로 생성되고 , heap 메모리는 하단부터 위로 메모리가 할당됩니다

StackOverFlow 의 주된 이유는 한정된 메모리 공간에 stack 메모리가 과도하게 호출이 되는 경우입니다.

즉 recursive에 terminate 조건이 없거나, terminate 조건이 있더라도 terminate 하기 전에 이미 stack 메모리가 초과되는 경우가 있는 것이죠.

Java가 예외를 Handling 하는 방법

그렇다면 이렇게 예외가 발생할경우 자바는 어떻게 예외를 핸들링할까요?

자바 클래스, 메서드에서 예외가 발생하면 예외가 발생한 지점에서 Exception 객체를 생성합니다.
생성된 객체는 JVM 위로 올라가게 됩니다.

 

그럼 런타임 시스템에서 위 그림처럼 stack 을 call 하며 단계별로 이동합니다.

어느 계층이 예외처리하기 가장 적합한 지점인지 탐색하고 적절한 지점에서 예외를 처리하게 되는 것이죠.

또, 자바의 예외는 세가지로 분류할 수 있습니다.

크게 Checked, Error, Runtime으로 구분할 수 있는데요. (Error, Runtime을 Unchecked라고 통칭하기도 합니다.)

 

Checked Exception은 컴파일러가 컴파일 타임에 체크해주는 예외입니다.

위 사진처럼 I/O에 접근이 불가한 경우를 대비하여 컴파일 시점에 try/catch를 달거나, throws 하라고 오류를 뱉는 것이 Checked 예외라고 볼 수 있습니다.

Error는 Java 프로그램 외부에서 발생하는 에러입니다. 즉 StackOverFlow와 같이 JVM에서 발생하는 에러가 그 대표 사례입니다.

 

마지막으로 Runtime 에러는 Java 프로그램 내부에서 발생하는 에러를 말합니다. NullPointerException이나 ArrayIndexOutOfBounds 처럼 Java 프로그램 내부 문제가 그 대표 사례입니다.

마무리

자바 에러 종류를 아는 것은 중요합니다. 특히 Spring으로 넘어갔을 때 더 많은 에러를 만나고 해결하기 위해서는 에러를 처리하는 방법에 대해 알아둬야 합니다.

 

이 포스팅으로 Java가 어떻게 예외를 처리하는지, 예외의 종류에는 무엇이 있는지 알아갈 수 있었습니다.