是否有任何条件最终可能无法在java中运行?感谢。
答案 0 :(得分:136)
注意:如果JVM在尝试时退出 或者正在执行catch代码 finally块可能无法执行。 同样,如果线程执行 尝试或捕获代码被中断或 杀了,终于阻止了 即使应用程序执行也执行 整体还在继续。
我不知道finally块不会执行任何其他方式......
答案 1 :(得分:62)
System.exit关闭虚拟机。
终止当前运行的Java 虚拟机。这个论点有用 作为状态代码;按惯例,a 非零状态代码表示异常 终止。
此方法调用
exit
方法 班Runtime
。从来没有这种方法 正常回归。
try {
System.out.println("hello");
System.exit(0);
}
finally {
System.out.println("bye");
} // try-finally
“bye”不会在上面的代码中打印出来。
答案 2 :(得分:49)
为了扩展其他人所说的内容,任何不会导致JVM退出的事情都将导致finally块。所以方法如下:
public static int Stupid() {
try {
return 0;
}
finally {
return 1;
}
}
奇怪地编译并返回1。
答案 3 :(得分:15)
与System.exit相关,还存在某些类型的灾难性故障,其中finally块可能无法执行。如果JVM完全耗尽内存,它可能会在没有捕获或最终发生的情况下退出。
具体来说,我记得一个我们愚蠢地尝试使用
的项目catch (OutOfMemoryError oome) {
// do stuff
}
这不起作用,因为JVM没有剩余的内存来执行catch块。
答案 4 :(得分:10)
try { for (;;); } finally { System.err.println("?"); }
在这种情况下,finally将不会执行(除非调用已弃用的Thread.stop
,或者通过工具接口调用等效项。)
答案 5 :(得分:8)
此主题中错误地引用了Sun教程。
注意:如果在执行try或catch代码时JVM退出,则finally块将不执行。同样,如果执行try或catch代码的线程被中断或终止,则即使整个应用程序仍在继续,finally块也将不执行。
如果你仔细研究sun教程中的finally块,它不会说“不会执行”但是“可能不会执行” 这是正确的描述
注意:如果在执行try或catch代码时JVM退出,则finally块可能不执行。同样,如果执行try或catch代码的线程被中断或终止,则即使应用程序作为一个整体继续,finally块可能也不会执行。
这种行为的明显原因是,在运行时系统线程中处理对system.exit()的调用,这可能需要一些时间来关闭jvm,同时线程调度程序可以最终要求执行。因此最终设计为始终执行,但如果您正在关闭jvm,则可能会发生jvm在最终执行之前关闭。
答案 6 :(得分:6)
此外,如果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”永远不会被打印
答案 7 :(得分:5)
以下是一些可以绕过finally块的条件:
最后一个非守护程序线程退出示例:
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
答案 8 :(得分:1)
有两种方法可以停止最终阻止代码执行:
1.使用System.exit();
2.如果执行控制无法达到尝试阻止的目的。
参见:
public class Main
{
public static void main (String[]args)
{
if(true){
System.out.println("will exceute");
}else{
try{
System.out.println("result = "+5/0);
}catch(ArithmeticException e){
System.out.println("will not exceute");
}finally{
System.out.println("will not exceute");
}
}
}
}
答案 9 :(得分:0)
我遇到了一个非常具体的例子,即finally块没有专门针对play框架执行。
我很惊讶地发现此控制器动作代码中的finally块仅在异常后调用,但从未在调用实际成功时调用。
try {
InputStream is = getInputStreamMethod();
renderBinary(is, "out.zip");
catch (Exception e) {
e.printStackTrace();
} finally {
cleanUp();
}
调用renderBinary()时,可能会终止线程或者某些东西。我怀疑其他render()调用会发生同样的事情,但我没有验证它。
我通过将renderBinary()移到try / catch之后解决了这个问题。进一步的调查显示,play提供了一个@Finally注释来创建一个在执行控制器动作后执行的方法。这里需要注意的是,在控制器中执行ANY操作后会调用它,所以它可能并不总是一个好的选择。
答案 10 :(得分:0)
在下列情况下,最终将不执行阻止: -
System.exit(0)
块调用try
时。 try
区块中的死锁条件可能还有其他边缘情况,最终阻止不会被执行。
答案 11 :(得分:-1)
//If ArithmeticException Occur Inner finally would not be executed
class Temp
{
public static void main(String[] s)
{
try
{
int x = 10/s.length;
System.out.println(x);
try
{
int z[] = new int[s.length];
z[10] = 1000;
}catch(ArrayIndexOutOfBoundsException e)
{
System.out.println(e);
}
finally
{
System.out.println("Inner finally");
}
}
catch(ArithmeticException e)
{
System.out.println(e);
}
finally
{
System.out.println("Outer Finally");
}
System.out.println("Remaining Code");
}
}