我了解异常,将其抛出,处理它们,并将其传播到调用堆栈中较低的方法(即throws
)。
我不明白的是:
public static void main(String[] args) throws Exception {
...
}
现在,我假设在main
抛出的情况下,Exception
JVM将对其进行处理(对吗?)。如果是这样,那么我的问题是:
JVM如何处理引发的异常main
?它有什么作用?
我了解异常,将其抛出,处理它们,并将其传播到调用堆栈中较低的方法(即throws
)。
我不明白的是:
public static void main(String[] args) throws Exception {
...
}
现在,我假设在main
抛出的情况下,Exception
JVM将对其进行处理(对吗?)。如果是这样,那么我的问题是:
JVM如何处理引发的异常main
?它有什么作用?
Answers:
您可能会认为public static void main
Java 中的方法或main
C中的函数是程序的真正入口点,但事实并非如此。所有高级语言(包括C)都具有语言运行时,该运行时会初始化程序,然后将控制流转移到入口点。对于Java,初始化将包括:
main
调用之前执行用户定义的代码。这些块不应该引发异常。有多种方法可以实现异常处理,但是出于这个问题的目的,它们都可以看作黑盒子。但是重要的是,语言运行时必须始终提供最外部的异常处理程序,以捕获用户代码未捕获的所有异常。该异常处理程序通常将打印出堆栈跟踪,以有序的方式关闭程序,并以错误代码退出。正确关闭程序包括破坏对象图,调用终结器以及释放诸如内存,文件句柄或网络连接之类的资源。
为了说明起见,您可以对运行时进行映像处理,将所有代码包装在一个看起来像
try {
loadClasses();
runInitializers();
main(argv);
System.exit(0);
} catch (Throwable e) {
e.printStackTrace();
System.exit(-1);
}
除了一种语言不必实际执行这样的代码外。可以在throw
搜索第一个适用的异常处理程序的代码(或等效代码)中实现相同的语义。
所有Java代码都在线程上下文中运行。链接的JavaDoc解释了错误处理和退出条件,但这是要点:
main()
使用任何适用的命令行参数来运行该方法。在未捕获的异常的情况下,该程序会根据以上第三项有效地死亡。Java语言规范的第11.3节中进一步指定了此行为。
其他人提到静态块以及它们之前如何执行main()
。但是,这需要更多的解释才能正确理解。
当加载一个类,类加载器必须初始化所有static final
状态和运行所有static
块之前的类都可以使用,以包括类(除了的实例实例:创建其中一类恒定在静态块初始化一个Java类之后创建类的实例,构造函数引用常量。但是,这一切在类加载器逻辑中发生,然后任何代码都可以引用该类。此外,该类会在引用该类的任何线程中加载。
这意味着如果包含的类main()
引用了另一个类(例如,类常量),则必须在main()
执行该类之前加载该类以包含其静态块。否则,将按上述方式执行静态块。如果无法加载该类,则包含该类的类main()
也将无法加载,程序将终止。
仅供参考:静态块可以抛出。Errors
按原样抛出。Exceptions
被禁止(编译时错误)。RuntimeExceptions
被包装在ExceptionInInitializerError中。这些都是每个未捕获异常处理程序,它通常要么杀死线程或应用程序(主线程),除非你仔细包裹在一个类的引用(和加载)处理try
- catch
。