是否有任何条件最终可能无法在java中运行?谢谢.
来自Sun教程
注意:如果在执行try或catch代码时JVM退出,则finally块可能无法执行.同样,如果执行try或catch代码的线程被中断或终止,则即使应用程序作为一个整体继续,finally块也可能无法执行.
我不知道finally块不会执行的任何其他方式......
System.exit关闭虚拟机.
终止当前运行的Java虚拟机.该参数用作状态代码; 按照惯例,非零状态代码表示异常终止.
此方法
exit
在类中调用该方法Runtime
.此方法永远不会正常返回.
try { System.out.println("hello"); System.exit(0); } finally { System.out.println("bye"); } // try-finally
"bye"不会在上面的代码中打印出来.
只是为了扩展其他人所说的内容,任何不会导致JVM退出的事情都将导致finally块.所以方法如下:
public static int Stupid() { try { return 0; } finally { return 1; } }
会奇怪地编译并返回1.
与System.exit相关,还存在某些类型的灾难性故障,其中finally块可能无法执行.如果JVM完全耗尽内存,它可能会在没有捕获或最终发生的情况下退出.
具体来说,我记得一个我们愚蠢地试图使用的项目
catch (OutOfMemoryError oome) { // do stuff }
这不起作用,因为JVM没有剩余的内存来执行catch块.
try { for (;;); } finally { System.err.println("?"); }
在这种情况下,finally将不会执行(除非Thread.stop
调用deprecated ,或者通过工具接口等效).
这个帖子中的Sun教程被错误地引用了.
注意:如果在执行try或catch代码时JVM退出,则finally块将不会执行.同样,如果执行try或catch代码的线程被中断或终止,则即使应用程序作为一个整体继续,finally块也不会执行.
如果你仔细研究sun教程中的finally块,它不会说"不会执行"但是"可能不会执行"这里是正确的描述
注意:如果在执行try或catch代码时JVM退出,则finally块可能无法执行.同样,如果执行try或catch代码的线程被中断或终止,则即使应用程序作为一个整体继续,finally块也可能无法执行.
这种行为的明显原因是,在运行时系统线程中处理对system.exit()的调用,这可能需要一些时间来关闭jvm,同时线程调度程序可以最终要求执行.因此最终设计为始终执行,但如果您正在关闭jvm,可能会发生jvm在最终执行之前关闭.
此外,如果在try
块内发生死锁/活锁.
这是演示它的代码:
public class DeadLocker { private static class SampleRunnable implements Runnable { private String threadId; private Object lock1; private Object lock2; public SampleRunnable(String threadId, Object lock1, Object lock2) { super(); this.threadId = threadId; this.lock1 = lock1; this.lock2 = lock2; } @Override public void run() { try { synchronized (lock1) { System.out.println(threadId + " inside lock1"); Thread.sleep(1000); synchronized (lock2) { System.out.println(threadId + " inside lock2"); } } } catch (Exception e) { } finally { System.out.println("finally"); } } } public static void main(String[] args) throws Exception { Object ob1 = new Object(); Object ob2 = new Object(); Thread t1 = new Thread(new SampleRunnable("t1", ob1, ob2)); Thread t2 = new Thread(new SampleRunnable("t2", ob2, ob1)); t1.start(); t2.start(); } }
此代码生成以下输出:
t1 inside lock1 t2 inside lock1
并且"终于"永远不会被打印出来
以下是一些可以绕过finally块的条件:
如果在执行try或catch代码时JVM退出,则finally块可能不会执行。
正常关机-在最后一个非守护程序线程退出时或在Runtime.exit()时发生
当线程退出时,JVM将对正在运行的线程进行清点,并且如果仅剩下的线程是守护程序线程,它将启动有序关闭。当JVM暂停时,所有剩余的守护程序线程都将被放弃,最后不执行块,堆栈也不会解开,只是退出JVM。应当尽可能少地使用守护程序线程,很少有处理活动可以在不清理的情况下随时安全地放弃。特别是,将守护程序线程用于可能执行任何I / O的任务是很危险的。最好将守护程序线程保存起来以用于“整理”任务,例如后台线程会定期从内存缓存中删除过期的条目。
最后一个非守护程序线程退出示例:
public class TestDaemon { private static Runnable runnable = new Runnable() { @Override public void run() { try { while (true) { System.out.println("Is alive"); Thread.sleep(10); // throw new RuntimeException(); } } catch (Throwable t) { t.printStackTrace(); } finally { System.out.println("This will never be executed."); } } }; public static void main(String[] args) throws InterruptedException { Thread daemon = new Thread(runnable); daemon.setDaemon(true); daemon.start(); Thread.sleep(100); // daemon.stop(); System.out.println("Last non-daemon thread exits."); } }
输出:
Is alive Is alive Is alive Is alive Is alive Is alive Is alive Is alive Is alive Is alive Last non-daemon thread exits. Is alive Is alive Is alive Is alive Is alive