2023-java-study / book-study

북 스터디 기록 레포지토리
0 stars 0 forks source link

[item 8] finalizer 동작 중 발생한 예외 처리의 랜덤성? #18

Closed NuhGnod closed 1 year ago

NuhGnod commented 1 year ago

p. 41, 42에 finalizer 동작 중 발생한 예외는 무시되며, 처리할 작업이 남았더라도 그 순간 종료된다.

public class item8 {

    public static void main(String[] args) throws IOException {
        String firstLine = new Finalizable().readFirstLine();
        System.out.println("firstLine = " + firstLine);
//        assertEquals("baeldung.com", firstLine);
        System.gc();
    }
}

class Finalizable {
    private BufferedReader reader;

    public Finalizable() throws FileNotFoundException {

        InputStream input = new FileInputStream("src/item8/file.txt");
        this.reader = new BufferedReader(new InputStreamReader(input));
    }

    public String readFirstLine() throws IOException {
        String firstLine = reader.readLine();
        return firstLine;
    }

    @Override
    protected void finalize() throws Throwable {
        try {
            reader.close();

            System.out.println("Closed BufferedReader in the finalizer");
//            throw new RuntimeException("일부로.");
            int arr[] = new int[10];
            arr[100]  =123;
        } catch (Exception e) {
            System.out.println("e = " + e);
        }
        super.finalize();
    }
}

위 코드로 테스트 해봤는데요, throw new RuntimeException("일부로."); 로 예외를 발생시킨 경우 catch문 까지 타고 들어가는 경우도 있었습니다. 반면에 arr[100] = 123; 으로 인덱스예외를 내면 catch문으로 가지 않고 책에서 말한대로 바로 종료 됩니다.

Object 클래스에서 finalize() 에 대한 설명을 보시면 좀 더 정확하게는, (493 line) If an uncaught exception is thrown by the finalize method, the exception is ignored and finalization of that object terminates. 라고 나와있습니다.

Q. throw new RuntimeException() 예외가 가끔 catch문을 타게 되는 이유..? uncaught exception 이 예외 처리 하지 않는 exception 으로 알았는데, catch(Excetion e){ } 로 다 처리 하고 있는데 위와 같은 현상이 일어난 점?이 이해가 가지 않네요..!

ssstopeun commented 1 year ago

저도 작성하신 것으로 테스트해봤는데 될 때가 있고 안될 때가 있더라구요. 그런데 If an uncaught exception is thrown by the finalize method, the exception is ignored and finalization of that object terminates. 이 말대로라면 try-catch로는 예외처리가 되야 하는게 맞는 것 같아서 혹시 예외까지 출력하는데 시간이 부족한 건가 생각했습니다.

public class catchExample {

    public static void main(String[] args) throws IOException, InterruptedException {
        String firstLine = new Finalizable().readFirstLine();
        System.out.println("firstLine = " + firstLine);
        System.gc();
        sleep(1000);
    }
}

System.gc()를 한 후에 프로그램 종료까지 시간을 주니 작성하신 코드가 catch문에서 error처리를 항상 하더라구요. 이게 왜인지 정확하게는 모르겠는데 finalize()를 finalize쓰레드가 실행하는 도중에 작업을 다 완료를 안했는데 프로그램이 종료된 상황이 아닌가 생각이 들었습니다... 그래서 운이 좋아 프로그램 종료전에 다 실행이될때는 error문장까지 출력이 되고 그것이 아니라면 출력이 안되는거 아닌가...



    @Override
    protected void finalize() throws Throwable {
            reader.close();

            System.out.println("Closed BufferedReader in the finalizer");

            int arr[] = new int[10];
            arr[100]  =123;

            System.out.println("eroor가 발생했습니다.");
        super.finalize();
    }

다른 코드가 동일한 상태에서 try-catch 처리를 안하고 error가 발생되게 해보았는데 이 경우는 finalizer의 문제점처럼 error이후의 코드인 'System.out.println("eroor가 발생했습니다.");' 를 전혀 처리하지 않았습니다.

try-catch는 예외처리가 잘되는 것 같은데 왜 경우에 따라 catch문이 잘 작동되고 안되는지는 같이 얘기해보면 좋을 것 같아요ㅠㅠ