Does a finally block always get executed in Java?

前端 未结 30 1557
逝去的感伤
逝去的感伤 2020-11-21 07:24

Considering this code, can I be absolutely sure that the finally block always executes, no matter what something() is?

try         


        
30条回答
  •  野性不改
    2020-11-21 07:50

    I tried this, It is single threaded.

    public static void main(String args[]) throws Exception {
        Object obj = new Object();
        try {
            synchronized (obj) {
                obj.wait();
                System.out.println("after wait()");
            }
        } catch (Exception ignored) {
        } finally {
            System.out.println("finally");
        }
    }
    

    The main Thread will be on wait state forever, hence finally will never be called,

    so console output will not print String: after wait() or finally

    Agreed with @Stephen C, the above example is one of the 3rd case mention here:

    Adding some more such infinite loop possibilities in following code:

    // import java.util.concurrent.Semaphore;
    
    public static void main(String[] args) {
        try {
            // Thread.sleep(Long.MAX_VALUE);
            // Thread.currentThread().join();
            // new Semaphore(0).acquire();
            // while (true){}
            System.out.println("after sleep join semaphore exit infinite while loop");
        } catch (Exception ignored) {
        } finally {
            System.out.println("finally");
        }
    }
    

    Case 2: If the JVM crashes first

    import sun.misc.Unsafe;
    import java.lang.reflect.Field;
    
    public static void main(String args[]) {
        try {
            unsafeMethod();
            //Runtime.getRuntime().halt(123);
            System.out.println("After Jvm Crash!");
        } catch (Exception e) {
        } finally {
            System.out.println("finally");
        }
    }
    
    private static void unsafeMethod() throws NoSuchFieldException, IllegalAccessException {
        Field f = Unsafe.class.getDeclaredField("theUnsafe");
        f.setAccessible(true);
        Unsafe unsafe = (Unsafe) f.get(null);
        unsafe.putAddress(0, 0);
    }
    

    Ref: How do you crash a JVM?

    Case 6: If finally block is going to be executed by daemon Thread and all other non-daemon Threads exit before finally is called.

    public static void main(String args[]) {
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                try {
                    printThreads("Daemon Thread printing");
                    // just to ensure this thread will live longer than main thread
                    Thread.sleep(10000);
                } catch (Exception e) {
                } finally {
                    System.out.println("finally");
                }
            }
        };
        Thread daemonThread = new Thread(runnable);
        daemonThread.setDaemon(Boolean.TRUE);
        daemonThread.setName("My Daemon Thread");
        daemonThread.start();
        printThreads("main Thread Printing");
    }
    
    private static synchronized void printThreads(String str) {
        System.out.println(str);
        int threadCount = 0;
        Set threadSet = Thread.getAllStackTraces().keySet();
        for (Thread t : threadSet) {
            if (t.getThreadGroup() == Thread.currentThread().getThreadGroup()) {
                System.out.println("Thread :" + t + ":" + "state:" + t.getState());
                ++threadCount;
            }
        }
        System.out.println("Thread count started by Main thread:" + threadCount);
        System.out.println("-------------------------------------------------");
    }
    

    output: This does not print "finally" which implies "Finally block" in "daemon thread" did not execute

    main Thread Printing  
    Thread :Thread[My Daemon Thread,5,main]:state:BLOCKED  
    Thread :Thread[main,5,main]:state:RUNNABLE  
    Thread :Thread[Monitor Ctrl-Break,5,main]:state:RUNNABLE   
    Thread count started by Main thread:3  
    -------------------------------------------------  
    Daemon Thread printing  
    Thread :Thread[My Daemon Thread,5,main]:state:RUNNABLE  
    Thread :Thread[Monitor Ctrl-Break,5,main]:state:RUNNABLE  
    Thread count started by Main thread:2  
    -------------------------------------------------  
    
    Process finished with exit code 0
    

提交回复
热议问题