Java 中的finally 块总是被执行吗?

发布于 2024-07-05 07:56:28 字数 306 浏览 10 评论 0原文

考虑到这段代码,我是否可以绝对确定 finally 块始终执行,无论 something() 是什么?

try {  
    something();  
    return success;  
}  
catch (Exception e) {   
    return failure;  
}  
finally {  
    System.out.println("I don't know if this will get printed out");
}

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

try {  
    something();  
    return success;  
}  
catch (Exception e) {   
    return failure;  
}  
finally {  
    System.out.println("I don't know if this will get printed out");
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(30

彡翼 2024-07-12 07:56:28

是的,finally 将在执行 trycatch 代码块后被调用。

唯一不会调用 finally 的情况是:

  1. 如果您调用 System.exit()
  2. 如果您调用 Runtime.getRuntime().halt(exitStatus)< /code>
  3. 如果 JVM 首先崩溃
  4. 如果 JVM 在 trycatch 块中达到无限循环(或其他一些不可中断、非终止语句)
  5. 如果OS强制终止JVM进程; 例如,UNIX 上的 kill -9
  6. 如果主机系统死机; 例如,电源故障、硬件错误、操作系统恐慌等
  7. 如果finally块将由守护线程执行,并且所有其他非守护线程在finally之前退出叫做

Yes, finally will be called after the execution of the try or catch code blocks.

The only times finally won't be called are:

  1. If you invoke System.exit()
  2. If you invoke Runtime.getRuntime().halt(exitStatus)
  3. If the JVM crashes first
  4. If the JVM reaches an infinite loop (or some other non-interruptable, non-terminating statement) in the try or catch block
  5. If the OS forcibly terminates the JVM process; e.g., kill -9 <pid> on UNIX
  6. If the host system dies; e.g., power failure, hardware error, OS panic, et cetera
  7. If the finally block is going to be executed by a daemon thread and all other non-daemon threads exit before finally is called
撕心裂肺的伤痛 2024-07-12 07:56:28

finally 总是被执行,除非程序异常终止(比如调用 System.exit(0))。 因此,您的 System.out 将被打印。

finally is always executed unless there is abnormal program termination (like calling System. exit(0)). so, your System.out will get printed.

弄潮 2024-07-12 07:56:28

除非出现异常程序终止(由于 JVM 崩溃或调用 System.exit(0) 导致),否则 Final 块始终会执行。

最重要的是,从finally块中返回的任何值都将覆盖执行finally块之前返回的值,因此在使用tryfinally时要小心检查所有退出点。

The finally block is always executed unless there is abnormal program termination, either resulting from a JVM crash or from a call to System.exit(0).

On top of that, any value returned from within the finally block will override the value returned prior to execution of the finally block, so be careful of checking all exit points when using try finally.

七七 2024-07-12 07:56:28

不,并非总是如此,一种例外情况是
System.exit(0);
finally 块之前阻止执行 finally

      class A {
        public static void main(String args[]) {
            DataInputStream cin = new DataInputStream(System.in);

            try {
                int i = Integer.parseInt(cin.readLine());
            } catch (ArithmeticException e) {
            } catch (Exception e) {
               System.exit(0); // Program terminates before executing the finally block
            } finally {
                System.out.println("Won't be executed");
                System.out.println("No error");
            }
        }
    }

No, not always, one exception case is
System.exit(0);
before the finally block prevents finally to be executed.

      class A {
        public static void main(String args[]) {
            DataInputStream cin = new DataInputStream(System.in);

            try {
                int i = Integer.parseInt(cin.readLine());
            } catch (ArithmeticException e) {
            } catch (Exception e) {
               System.exit(0); // Program terminates before executing the finally block
            } finally {
                System.out.println("Won't be executed");
                System.out.println("No error");
            }
        }
    }
我爱人 2024-07-12 07:56:28

这就是finally 块的全部思想。 当然,它可以让您确保进行清理工作,否则这些清理工作可能会因为您返回而被跳过。

无论 try 块中发生什么,finally 都会被调用(除非您调用 System.exit(int) 或 Java 虚拟机退出其他一些原因)。

That is the whole idea of a finally block. It lets you make sure you do cleanups that might otherwise be skipped because you return, among other things, of course.

Finally gets called regardless of what happens in the try block (unless you call System.exit(int) or the Java Virtual Machine kicks out for some other reason).

怕倦 2024-07-12 07:56:28

思考这个问题的逻辑方法是:

  1. 放置在finally块中的代码必须在try块中无论发生什么执行
  2. 因此,如果try块中的代码尝试返回一个值或抛出一个异常,则该项目是放在“架子上”直到finally块可以执行
  3. 因为finally块中的代码(根据定义)具有高优先级,它可以返回或抛出任何它喜欢的东西。 在这种情况下,“架子上”留下的任何东西都会被丢弃。
  4. 唯一的例外是虚拟机在 try 块期间完全关闭,例如通过“System.exit”

A logical way to think about this is:

  1. Code placed in a finally block must be executed whatever occurs within the try block
  2. So if code in the try block tries to return a value or throw an exception the item is placed 'on the shelf' till the finally block can execute
  3. Because code in the finally block has (by definition) a high priority it can return or throw whatever it likes. In which case anything left 'on the shelf' is discarded.
  4. The only exception to this is if the VM shuts down completely during the try block e.g. by 'System.exit'
云巢 2024-07-12 07:56:28

以下是凯文的回答的详细阐述。 重要的是要知道要返回的表达式是在 finally 之前计算的,即使它是在之后返回的。

public static void main(String[] args) {
    System.out.println(Test.test());
}

public static int printX() {
    System.out.println("X");
    return 0;
}

public static int test() {
    try {
        return printX();
    }
    finally {
        System.out.println("finally trumps return... sort of");
        return 42;
    }
}

输出:

X
finally trumps return... sort of
42

Here's an elaboration of Kevin's answer. It's important to know that the expression to be returned is evaluated before finally, even if it is returned after.

public static void main(String[] args) {
    System.out.println(Test.test());
}

public static int printX() {
    System.out.println("X");
    return 0;
}

public static int test() {
    try {
        return printX();
    }
    finally {
        System.out.println("finally trumps return... sort of");
        return 42;
    }
}

Output:

X
finally trumps return... sort of
42
风启觞 2024-07-12 07:56:28

我尝试了上面的例子,稍加修改 -

public static void main(final String[] args) {
    System.out.println(test());
}

public static int test() {
    int i = 0;
    try {
        i = 2;
        return i;
    } finally {
        i = 12;
        System.out.println("finally trumps return.");
    }
}

上面的代码输出:

终于战胜了回归。
2

这是因为当执行 return i; 时,i 的值为 2。此后执行 finally 块,其中 12 被分配给 < code>i 然后执行 System.out out。

执行finally 块后,try 块返回2,而不是返回12,因为该return 语句不会再次执行。

如果您在 Eclipse 中调试这段代码,那么您会感觉到,在执行 finallySystem.out 后,会阻塞 return 语句。 code>try 块再次执行。 但这种情况并非如此。 它只是返回值 2。

I tried the above example with slight modification-

public static void main(final String[] args) {
    System.out.println(test());
}

public static int test() {
    int i = 0;
    try {
        i = 2;
        return i;
    } finally {
        i = 12;
        System.out.println("finally trumps return.");
    }
}

The above code outputs:

finally trumps return.
2

This is because when return i; is executed i has a value 2. After this the finally block is executed where 12 is assigned to i and then System.out out is executed.

After executing the finally block the try block returns 2, rather than returning 12, because this return statement is not executed again.

If you will debug this code in Eclipse then you'll get a feeling that after executing System.out of finally block the return statement of try block is executed again. But this is not the case. It simply returns the value 2.

故事与诗 2024-07-12 07:56:28

除了其他响应之外,重要的是要指出“finally”有权通过 try..catch 块覆盖任何异常/返回值。 例如,以下代码返回 12:

public static int getMonthsInYear() {
    try {
        return 10;
    }
    finally {
        return 12;
    }
}

类似地,以下方法不会引发异常:

public static int getMonthsInYear() {
    try {
        throw new RuntimeException();
    }
    finally {
        return 12;
    }
}

而以下方法会引发异常:

public static int getMonthsInYear() {
    try {
        return 12;          
    }
    finally {
        throw new RuntimeException();
    }
}

In addition to the other responses, it is important to point out that 'finally' has the right to override any exception/returned value by the try..catch block. For example, the following code returns 12:

public static int getMonthsInYear() {
    try {
        return 10;
    }
    finally {
        return 12;
    }
}

Similarly, the following method does not throw an exception:

public static int getMonthsInYear() {
    try {
        throw new RuntimeException();
    }
    finally {
        return 12;
    }
}

While the following method does throw it:

public static int getMonthsInYear() {
    try {
        return 12;          
    }
    finally {
        throw new RuntimeException();
    }
}
朱染 2024-07-12 07:56:28

示例代码:

public static void main(String[] args) {
    System.out.println(Test.test());
}

public static int test() {
    try {
        return 0;
    }
    finally {
        System.out.println("something is printed");
    }
}

输出:

something is printed. 
0

Example code:

public static void main(String[] args) {
    System.out.println(Test.test());
}

public static int test() {
    try {
        return 0;
    }
    finally {
        System.out.println("something is printed");
    }
}

Output:

something is printed. 
0
等你爱我 2024-07-12 07:56:28

另外,尽管这是不好的做法,但如果 finally 块中有 return 语句,它将胜过常规块中的任何其他返回。 也就是说,以下块将返回 false:

try { return true; } finally { return false; }

与从 finally 块抛出异常相同。

Also, although it's bad practice, if there is a return statement within the finally block, it will trump any other return from the regular block. That is, the following block would return false:

try { return true; } finally { return false; }

Same thing with throwing exceptions from the finally block.

雪若未夕 2024-07-12 07:56:28

以下是 Java 语言规范的官方措辞。

14.20.2。 try-finally 和 try-catch-finally 的执行

带有 finally 块的 try 语句首先执行 try 块来执行。 然后有一个选择:

  • 如果 try 块的执行正常完成,[...]
  • 如果 try 块的执行由于 V 值的 throw 突然完成,[...]
  • 如果 try 块的执行由于任何其他原因突然完成R,则执行 finally 块。 然后有一个选择:
    • 如果finally 块正常完成,则try 语句会由于R 的原因突然完成。
    • 如果 finally 块因 S 原因突然完成,则 try 语句因 S 原因突然完成(以及R被丢弃的原因)。

return 的规范实际上明确了这一点:

JLS 14.17 退货声明

返回语句: 
       返回表达式(选择); 
  

没有表达式return语句尝试将控制转移到包含它的方法或构造函数的调用者。

带有表达式return语句尝试将控制权转移到包含它的方法的调用者; Expression 的值成为方法调用的值。

前面的描述说的是“尝试转移控制权”,而不仅仅是“转移控制权”,因为如果有任何尝试方法或构造函数中的 语句,其 try 块包含 return 语句,然后是这些 try< 的任何 finally 子句在控制权转移到方法或构造函数的调用者之前, /code> 语句将按从最内层到最外层的顺序执行。 finally 子句的突然完成可能会中断 return 语句启动的控制权转移。


Here's the official words from the Java Language Specification.

14.20.2. Execution of try-finally and try-catch-finally

A try statement with a finally block is executed by first executing the try block. Then there is a choice:

  • If execution of the try block completes normally, [...]
  • If execution of the try block completes abruptly because of a throw of a value V, [...]
  • If execution of the try block completes abruptly for any other reason R, then the finally block is executed. Then there is a choice:
    • If the finally block completes normally, then the try statement completes abruptly for reason R.
    • If the finally block completes abruptly for reason S, then the try statement completes abruptly for reason S (and reason R is discarded).

The specification for return actually makes this explicit:

JLS 14.17 The return Statement

ReturnStatement:
     return Expression(opt) ;

A return statement with no Expression attempts to transfer control to the invoker of the method or constructor that contains it.

A return statement with an Expression attempts to transfer control to the invoker of the method that contains it; the value of the Expression becomes the value of the method invocation.

The preceding descriptions say "attempts to transfer control" rather than just "transfers control" because if there are any try statements within the method or constructor whose try blocks contain the return statement, then any finally clauses of those try statements will be executed, in order, innermost to outermost, before control is transferred to the invoker of the method or constructor. Abrupt completion of a finally clause can disrupt the transfer of control initiated by a return statement.

清眉祭 2024-07-12 07:56:28

最后总是运行,这就是重点,仅仅因为它出现在返回之后的代码中并不意味着这就是它的实现方式。 Java 运行时有责任在退出 try 块时运行此代码。

例如,如果您有以下内容:

int foo() { 
    try {
        return 42;
    }
    finally {
        System.out.println("done");
    }
}

运行时将生成如下内容:

int foo() {
    int ret = 42;
    System.out.println("done");
    return 42;
}

如果抛出未捕获的异常,finally 块将运行并且异常将继续传播。

Finally is always run that's the whole point, just because it appears in the code after the return doesn't mean that that's how it's implemented. The Java runtime has the responsibility to run this code when exiting the try block.

For example if you have the following:

int foo() { 
    try {
        return 42;
    }
    finally {
        System.out.println("done");
    }
}

The runtime will generate something like this:

int foo() {
    int ret = 42;
    System.out.println("done");
    return 42;
}

If an uncaught exception is thrown the finally block will run and the exception will continue propagating.

冷心人i 2024-07-12 07:56:28

因为除非你调用 System.exit() (或者线程崩溃),否则finally 块将始终被调用。

Because a finally block will always be called unless you call System.exit() (or the thread crashes).

献世佛 2024-07-12 07:56:28

简而言之,在官方 Java 文档(点击此处)中,写道——

如果在执行 try 或 catch 代码时 JVM 退出,则
finally 块可能不会执行。 同样,如果线程执行
try 或 catch 代码被中断或终止,finally 块可能
即使应用程序作为一个整体继续运行,也不会执行。

Concisely, in the official Java Documentation (Click here), it is written that -

If the JVM exits while the try or catch code is being executed, then
the finally block may not execute. Likewise, if the thread executing
the try or catch code is interrupted or killed, the finally block may
not execute even though the application as a whole continues.

人生戏 2024-07-12 07:56:28

这是因为您将 i 的值指定为 12,但没有将 i 的值返回给函数。 正确的代码如下:

public static int test() {
    int i = 0;
    try {
        return i;
    } finally {
        i = 12;
        System.out.println("finally trumps return.");
        return i;
    }
}

This is because you assigned the value of i as 12, but did not return the value of i to the function. The correct code is as follows:

public static int test() {
    int i = 0;
    try {
        return i;
    } finally {
        i = 12;
        System.out.println("finally trumps return.");
        return i;
    }
}
一百个冬季 2024-07-12 07:56:28

是的,它会被调用。 这就是finally 关键字的全部意义所在。 如果跳出 try/catch 块可以跳过 finally 块,则与将 System.out.println 放在 try/catch 之外是一样的。

Yes it will get called. That's the whole point of having a finally keyword. If jumping out of the try/catch block could just skip the finally block it was the same as putting the System.out.println outside the try/catch.

最偏执的依靠 2024-07-12 07:56:28

并不总是

Java 语言规范描述了 try-catch-finallytry-catch 的方式code> 块在 14.20 工作.2
它没有在任何地方指定始终执行 finally 块。
但对于 try-catch-finallytry-finally 的所有情况> 块完成它确实指定在完成之前必须执行finally

try {
  CODE inside the try block
}
finally {
  FIN code inside finally block
}
NEXT code executed after the try-finally block (may be in a different method).

JLS 不保证FINCODE 之后执行。
JLS 保证如果执行CODENEXT,则FIN 将始终在CODE 之后和之前执行。 >下一步

为什么 JLS 不保证 finally 块始终在 try 块之后执行? 因为这是不可能的。 JVM 在完成 try 块之后但在执行 之前,不太可能但有可能中止(终止、崩溃、断电)。 code>finally 块。 JLS 无法采取任何措施来避免这种情况。

因此,任何依赖于总是在 try 块完成后执行的 finally 块来正常运行的软件都会被窃听。

try 块中的 return 指令与此问题无关。 如果执行到 try-catch-finally 之后的代码,则保证 finally 块将被执行之前,在 try 块内有或没有 return 指令。

NOT ALWAYS

The Java Language specification describes how try-catch-finally and try-catch blocks work at 14.20.2
In no place it specifies that the finally block is always executed.
But for all cases in which the try-catch-finally and try-finally blocks complete it does specify that before completion finally must be executed.

try {
  CODE inside the try block
}
finally {
  FIN code inside finally block
}
NEXT code executed after the try-finally block (may be in a different method).

The JLS does not guarantee that FIN is executed after CODE.
The JLS guarantees that if CODE and NEXT are executed then FIN will always be executed after CODE and before NEXT.

Why doesn't the JLS guarantee that the finally block is always executed after the try block? Because it is impossible. It is unlikely but possible that the JVM will be aborted (kill, crash, power off) just after completing the try block but before execution of the finally block. There is nothing the JLS can do to avoid this.

Thus, any software which for their proper behaviour depends on finally blocks always being executed after their try blocks complete are bugged.

return instructions in the try block are irrelevant to this issue. If execution reaches code after the try-catch-finally it is guaranteed that the finally block will have been executed before, with or without return instructions inside the try block.

温馨耳语 2024-07-12 07:56:28

finally 块始终在返回 x 的(计算出的)值之前执行。

System.out.println("x value from foo() = " + foo());

...

int foo() {
  int x = 2;
  try {
    return x++;
  } finally {
    System.out.println("x value in finally = " + x);
  }
}

输出:

最后的 x 值 = 3
foo() 的 x 值 = 2

finally block is always executed and before returning x's (calculated) value.

System.out.println("x value from foo() = " + foo());

...

int foo() {
  int x = 2;
  try {
    return x++;
  } finally {
    System.out.println("x value in finally = " + x);
  }
}

Output:

x value in finally = 3
x value from foo() = 2

半暖夏伤 2024-07-12 07:56:28

答案很简单

输入:

try{
    int divideByZeroException = 5 / 0;
} catch (Exception e) {
    System.out.println("catch");
    return;    // also tried with break; in switch-case, got same output
} finally {
    System.out.println("finally");
}

输出:

catch
finally

Answer is simple YES.

INPUT:

try{
    int divideByZeroException = 5 / 0;
} catch (Exception e) {
    System.out.println("catch");
    return;    // also tried with break; in switch-case, got same output
} finally {
    System.out.println("finally");
}

OUTPUT:

catch
finally
桃扇骨 2024-07-12 07:56:28

是的,它会。 无论 try 或 catch 块中发生什么,除非调用 System.exit() 或 JVM 崩溃。 如果块中有任何 return 语句,finally 将在该 return 语句之前执行。

Yes, it will. No matter what happens in your try or catch block unless otherwise System.exit() called or JVM crashed. if there is any return statement in the block(s),finally will be executed prior to that return statement.

遮云壑 2024-07-12 07:56:28

是的,它会。
唯一不会出现的情况是 JVM 退出或崩溃

Yes It will.
Only case it will not is JVM exits or crashes

小巷里的女流氓 2024-07-12 07:56:28

添加到 @vibhash 的答案,因为没有其他答案解释了在像下面这样的可变对象的情况下会发生什么。

public static void main(String[] args) {
    System.out.println(test().toString());
}

public static StringBuffer test() {
    StringBuffer s = new StringBuffer();
    try {
        s.append("sb");
        return s;
    } finally {
        s.append("updated ");
    }
}

会输出

sb更新  
  

Adding to @vibhash's answer as no other answer explains what happens in the case of a mutable object like the one below.

public static void main(String[] args) {
    System.out.println(test().toString());
}

public static StringBuffer test() {
    StringBuffer s = new StringBuffer();
    try {
        s.append("sb");
        return s;
    } finally {
        s.append("updated ");
    }
}

Will output

sbupdated 
一城柳絮吹成雪 2024-07-12 07:56:28

是的,finally 块总是被执行。 大多数开发人员使用此块来关闭数据库连接、结果集对象、语句对象,并且还使用 java hibernate 来回滚事务。

Yes, finally block is always execute. Most of developer use this block the closing the database connection, resultset object, statement object and also uses into the java hibernate to rollback the transaction.

比忠 2024-07-12 07:56:28

我对不同论坛上提供的所有答案感到非常困惑,并决定最终编码并查看。 输出是:

即使 try 和 catch 块中有 return,finally 也会被执行。

try {  
  System.out.println("try"); 
  return;
  //int  i =5/0;
  //System.exit(0 ) ;
} catch (Exception e) {   
  System.out.println("catch");
  return;
  //int  i =5/0;
  //System.exit(0 ) ;
} finally {  
   System.out.println("Print me FINALLY");
}

输出

尝试

最后打印我

  1. 如果上面代码中的 try 和 catch 块中的 return 被替换为 System.exit(0) ,并且无论出于何种原因,在它之前发生了异常。

I was very confused with all the answers provided on different forums and decided to finally code and see. The ouput is :

finally will be executed even if there is return in try and catch block.

try {  
  System.out.println("try"); 
  return;
  //int  i =5/0;
  //System.exit(0 ) ;
} catch (Exception e) {   
  System.out.println("catch");
  return;
  //int  i =5/0;
  //System.exit(0 ) ;
} finally {  
   System.out.println("Print me FINALLY");
}

Output

try

Print me FINALLY

  1. If return is replaced by System.exit(0) in try and catch block in above code and an exception occurs before it,for any reason.
等风来 2024-07-12 07:56:28

finally 将会执行,这是肯定的。

finally 在以下情况下不会执行:

情况 1:

当您执行 System.exit() 时。

情况 2:

当您的 JVM/线程崩溃时。

情况 3:

当您手动停止执行时。

finally will execute and that is for sure.

finally will not execute in below cases:

case 1 :

When you are executing System.exit().

case 2 :

When your JVM / Thread crashes.

case 3 :

When your execution is stopped in between manually.

流绪微梦 2024-07-12 07:56:28

我试过这个,
它是单线程的。

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");
    }
}

main Thread 将永远处于 wait 状态,因此 finally 永远不会被调用

因此控制台输出不会 print String:在 wait()finally

同意@Stephen C,上面的例子是这里提到的第三种情况之一:

在以下代码中添加更多这样的无限循环可能性:

// 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");
    }
}

情况2:如果 JVM 首先崩溃

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);
}

参考:如何使 JVM 崩溃?

案例 6:如果最后 block 将由守护进程 Thread 执行,所有其他非守护进程 Threads 在调用 finally 之前退出。

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<Thread> 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("-------------------------------------------------");
}

输出:这不会打印“finally”,这意味着“守护线程”中的“Finally block”没有执行

主线程打印   
  线程:线程[我的守护程序线程,5,主]:状态:BLOCKED   
  线程:线程[主,5,主]:状态:RUNNABLE   
  线程:线程[监视器 Ctrl-Break,5,main]:状态:RUNNABLE    
  主线程启动的线程数:3   
  -------------------------------------------------   
  守护线程打印   
  线程:线程[我的守护程序线程,5,主]:状态:RUNNABLE   
  线程:线程[监视器 Ctrl-Break,5,main]:状态:RUNNABLE   
  主线程启动的线程数:2   
  -------------------------------------------------   

  进程已完成,退出代码为 0 
  

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<Thread> 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
别靠近我心 2024-07-12 07:56:28

考虑以下程序:

public class SomeTest {

    private static StringBuilder sb = new StringBuilder();

    public static void main(String args[]) {

        System.out.println(someString());
        System.out.println("---AGAIN---");
        System.out.println(someString());
        System.out.println("---PRINT THE RESULT---");
        System.out.println(sb.toString());
    }

    private static String someString() {

        try {
            sb.append("-abc-");
            return sb.toString();

        } finally {
            sb.append("xyz");
        }
    }
}

从 Java 1.8.162 开始,上述代码块给出以下输出:

-abc-
---AGAIN---
-abc-xyz-abc-
---PRINT THE RESULT---
-abc-xyz-abc-xyz

这意味着使用 finally 来释放对象是一个很好的做法,如下代码所示:

private static String someString() {

    StringBuilder sb = new StringBuilder();

    try {
        sb.append("abc");
        return sb.toString();

    } finally {
        sb = null; // Just an example, but you can close streams or DB connections this way.
    }
}

Consider the following program:

public class SomeTest {

    private static StringBuilder sb = new StringBuilder();

    public static void main(String args[]) {

        System.out.println(someString());
        System.out.println("---AGAIN---");
        System.out.println(someString());
        System.out.println("---PRINT THE RESULT---");
        System.out.println(sb.toString());
    }

    private static String someString() {

        try {
            sb.append("-abc-");
            return sb.toString();

        } finally {
            sb.append("xyz");
        }
    }
}

As of Java 1.8.162, the above code block gives the following output:

-abc-
---AGAIN---
-abc-xyz-abc-
---PRINT THE RESULT---
-abc-xyz-abc-xyz

this means that using finally to free up objects is a good practice like the following code:

private static String someString() {

    StringBuilder sb = new StringBuilder();

    try {
        sb.append("abc");
        return sb.toString();

    } finally {
        sb = null; // Just an example, but you can close streams or DB connections this way.
    }
}
无语# 2024-07-12 07:56:28

这实际上在任何语言中都是如此......finally 总是在 return 语句之前执行,无论 return 位于方法体中的哪个位置。 如果不是这样,finally 块就没有多大意义。

That's actually true in any language...finally will always execute before a return statement, no matter where that return is in the method body. If that wasn't the case, the finally block wouldn't have much meaning.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文