Java中的运行时堆栈机制 [使用更新的图像]
先决条件: Java中的异常
对于每个线程,JVM(Java虚拟机)都会创建一个运行时堆栈。
- 线程中执行的每个调用都存储在堆栈中。
- 运行时堆栈中的每个条目称为激活记录或堆栈帧。
- 在线程完成每个方法调用后,从堆栈的相应条目中删除。
- 完成所有方法后,堆栈将为空,并且该运行时堆栈将在终止线程之前被 JVM 销毁。
让我们看一下下面的程序,以了解运行时堆栈的工作原理。
案例1:正常(优雅终止)
运行时栈的构建:
- 首先,主线程会调用main()方法,对应的入口会在栈中。
- 之后 main() 方法被称为 fun() 方法,它将存储在堆栈中。
- 在 fun() 方法中,调用了 moreFun() 方法。因此,最后 moreFun() 将存储在堆栈中。
- 最后,moreFun() 没有调用任何方法,它会打印Hello Geeks!
Java
// Java program to illustrate run time
// Run-time stack mechanism in
// normal flow of Exception handling
class Geeks {
public static void main(String[] args)
{
fun();
}
public static void fun()
{
moreFun();
}
public static void moreFun()
{
System.out.println("Hello Geeks!");
}
}
Java
// Java program to illustrate run time
// Run-time stack mechanism in
// normal flow of Exception handling
public class ExceptionHandling {
public static void main(String[] args)
{
fun();
}
public static void fun()
{
moreFun();
System.out.println("Method fun");
}
public static void moreFun()
{
System.out.println(10 / 0);
System.out.println("Method moreFun");
}
}
输出
Hello Geeks!
运行时堆栈的破坏:打印后Hello Geeks! ,其对应的条目将从堆栈中删除,它将转到 fun() 方法,并且没有任何执行内容,这就是为什么从堆栈中删除 fun() 方法的条目等等。当堆栈为空时,JVM 会销毁运行时堆栈。
案例2:异常(异常终止)
运行时栈的构建:
- 下面的示例在方法 moreFun() 位置有 ArithmeticException,JVM 将检查是否存在任何异常处理代码。如果不是,则方法 moreFun() 将负责创建异常对象,因为在方法 moreFun() 上引发了异常,并且将从堆栈中删除相应的条目,并且控制转到方法 fun()。
- JVM 再次去调用者方法检查它是否有任何异常处理代码都没有。如果不是,JVM 会异常终止该方法并从堆栈中删除相应的条目。
- 上述过程一直持续到主线程。如果主线程(main 方法)没有任何异常处理代码,JVM 也会异常终止 main 方法,默认异常处理程序负责将异常消息打印到作为 JVM 一部分的输出屏幕。
Java
// Java program to illustrate run time
// Run-time stack mechanism in
// normal flow of Exception handling
public class ExceptionHandling {
public static void main(String[] args)
{
fun();
}
public static void fun()
{
moreFun();
System.out.println("Method fun");
}
public static void moreFun()
{
System.out.println(10 / 0);
System.out.println("Method moreFun");
}
}
运行时错误:
Exception in thread "main" java.lang.ArithmeticException: / by zero
at ExceptionHandling.moreFun(ExceptionHandling.java:16)
at ExceptionHandling.fun(ExceptionHandling.java:11)
at ExceptionHandling.main(ExceptionHandling.java:7)