Java解惑4 39你好,再见!
下面的程序在寻常的Hello world程序中添加了一段不寻常的曲折操作。那么,它将会打印出什么呢?
public class HelloGoodbye {
public static void main(String[] args) {
try {
System.out.println("Hello world");
System.exit(0);
} finally {
System.out.println("Goodbye world");
}
}
}
这个程序包含两个println语句:一个在try语句块中,另一个在相应的finally语句块中。try语句块执行它的println语句,并且通过调用System.exit来提前结束执行。在此时,你可能希望控制权会转交给finally语句块。然而,如果你运行该程序,就会发现它永远不会说再见:它只打印了Hello world。这是否违背了谜题36中所解释的原则呢?
不论try语句块的执行是正常地还是意外地结束,finally语句块确实都会执行。然而在这个程序中,try语句块根本就没有结束其执行过程。System.exit方法将停止当前线程和所有其他当场死亡的线程。finally子句的出现并不能给予线程继续去执行的特殊权限。
当System.exit被调用时,虚拟机在关闭前要执行两项清理工作。首先,它执行所有的关闭挂钩操作,这些挂钩已经注册到了Runtime.addShutdownHook上。这对于释放VM之外的资源将很有帮助。务必要为那些必须在VM退出之前发生的行为关闭挂钩。下面的程序版本示范了这种技术,它可以如我们所期望地打印出Hello world和Goodbye world:
public class HelloGoodbye1 {
public static void main(String[] args) {
System.out.println("Hello world");
Runtime.getRuntime().addShutdownHook(
new Thread() {
public void run() {
System.out.println("Goodbye world");
}
});
System.exit(0);
}
}
VM执行在System.exit被调用时执行的第二个清理任务与终结器有关。如果System.runFinalizerOnExit或它的魔鬼双胞胎Runtime.runFinalizersOnExit被调用了,那么VM将在所有还未终结的对象上面调用终结器。这些方法很久以前就已经过时了,而且其原因也很合理。无论什么原因,永远不要调用System.runFinalizersOnExit和Runtime.runFinalizersOnExit:它们属于Java类库中最危险的方法之一[ThreadStop]。调用这些方法导致的结果是,终结器会在那些其他线程正在并发操作的对象上面运行,从而
相关文档:
2008 年 6 月 24 日
原文地址: http://www.ibm.com/developerworks/cn/data/library/techarticles/dm-0806wangys/
本文介绍 IBM FileNet P8 4.0 Platform 提供的 Content Java API。首先对 FileNet P8 Content Engine 和 API 进行概要介绍, 并说明了一些基本概念,随后详细介绍了 FileNet Content Engine提供的基于 EJB ......
下面的谜题以及随后的五个谜题对你来说是扭转了局面,它们不是向你展示某些代码,然后询问你这些代码将做些什么,它们要让你去写代码,但是数量会很少。这些谜题被称为“循环者(looper)”。你眼前会展示出一个循环,它看起来应该很快就终止的,而你的任务就是写一个变量声明,在将它作用于该循环之上时,使得该 ......
请提供一个对i的声明,将下面的循环转变为一个无限循环:
while (i != i + 0) {
}
与前一个谜题不同,你必须在你的答案中不使用浮点数。换句话说,你不能把i声明为double或float类型的。
与前一个谜题一样,这个谜题初看起来是不可能实现的。毕竟,一个数字总是等于它自身加上0,你被禁止使用浮点数,因此不能使用NaN ......
请提供一个对i的声明,将下面的循环转变为一个无限循环:
while (i != 0) {
i >>>= 1;
}
回想一下,>>>=是对应于无符号右移操作符的赋值操作符。0被从左移入到由移位操作而空出来的位上,即使被移位的负数也是如此。
这个循环比前面三个循环要稍微复杂一点,因为其循环体非空。在其循环题中, ......