有什么条件最终可能无法在Java中运行?谢谢。
有什么条件最终可能无法在Java中运行?谢谢。
Answers:
从太阳教程
注意:如果在执行try或catch代码时JVM退出,则finally块可能不会执行。同样,如果执行try或catch代码的线程被中断或杀死,即使整个应用程序继续运行,finally块也可能不会执行。
我不知道finally块不会执行任何其他方式...
System.exit关闭虚拟机。
终止当前正在运行的Java虚拟机。参数用作状态码;按照惯例,非零状态代码表示异常终止。
该方法调用
exit
class中的方法Runtime
。此方法永远不会正常返回。
try {
System.out.println("hello");
System.exit(0);
}
finally {
System.out.println("bye");
} // try-finally
“再见”不会在上述代码中打印出来。
只是为了进一步扩展别人所说的内容,任何不会导致诸如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
工具接口调用了不赞成使用的方法,或者等价的方法)。
throw
,则该finally
块将按预期执行。try { throw new ThreadDeath(); } finally { System.err.println("?"); }
该线程在此处错误地引用了Sun教程。
注意:如果在执行try或catch代码时JVM退出,则finally块将不会执行。同样,如果执行try或catch代码的线程被中断或杀死,即使整个应用程序继续运行,finally块也不会执行。
如果您仔细查看sun教程中的“ finally”块,它不会说“将不执行”,而是“可能不执行”
注意:如果在执行try或catch代码时JVM退出,则finally块可能不会执行。同样,如果执行try或catch代码的线程被中断或杀死,即使整个应用程序继续运行,finally块也可能不会执行。
出现这种现象的明显原因是,对system.exit()的调用在运行时系统线程中处理,这可能需要一些时间来关闭jvm,同时线程调度程序可以最终要求执行。因此,finally设计为始终执行,但是如果要关闭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
并且“最终”永远不会被打印
如果在执行try或catch代码时JVM退出,则finally块可能不会执行。(来源)
正常关机-在最后一个非守护程序线程退出时或在Runtime.exit()(source)时发生
当线程退出时,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
在以下情况下,finally块将不会执行:
System.exit(0)
从try
块中调用何时。 try
块中的 死锁条件可能还有其他附带情况,其中不会执行finally块。
有两种方法可以停止最终阻止代码执行:
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");
}
}
}
}
我遇到了一个非常特殊的情况,即finally块未执行,这与播放框架有关。
我很惊讶地发现,该控制器操作代码中的finally块仅在Exception之后才被调用,而在调用实际上没有成功时才被调用。
try {
InputStream is = getInputStreamMethod();
renderBinary(is, "out.zip");
catch (Exception e) {
e.printStackTrace();
} finally {
cleanUp();
}
也许线程终止了,或者在调用renderBinary()时发生了什么。我怀疑其他的render()调用也会发生同样的事情,但是我没有验证。
我通过在try / catch之后将renderBinary()移至来解决了这个问题。进一步的调查显示,play提供了@Finally批注以创建一种方法,该方法在执行控制器动作后将被执行。需要注意的是,这将在控制器中执行ANY操作之后被调用,因此它不一定总是一个不错的选择。
//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");
}
}