java

关注公众号 jb51net

关闭
首页 > 软件编程 > java > Java 虚拟机栈

Java 虚拟机栈详解分析

作者:小小奶酪可笑可笑

在线程创建时,JVM会为每个线程创建一个单独的栈空间。JVM的栈内存不需要是连续的。JVM在栈上会进行两个操作:压入和弹出栈帧。对于一个特定的线程来说,栈被称为运行时栈。这个线程调用的每个方法会被存储在响应的运行时栈里,包括了参数,局部变量,计算媒介和其他数据

Java虚拟机栈

1. 定义

现在我们用代码来演示一下Java虚拟机如何将栈帧压入及压出栈中

 public class Main {
     public static void main(String[] args) {
         method1();
     }
     
     private static void method1() {
         method2(1, 2);
     }
     
     private static int method2(int a, int b) {
         int c = a + b;
         return c;
     }
 }

当我们运行Main函数时,jvm首先将栈帧Main压入栈中,此视栈结构如图所示

Main函数体中调用了method1方法,此时便会将栈帧1压入栈中

method1方法体中调用了method2方法,这时jvm会将栈帧2压入栈结构中,需要注意的是,前面我们提到了栈帧由 “局部变量表、操作数栈、动态链接和方法返回值”等信息组成,method2方法中拥有a,b两个参数以及局部变量c和方法返回值

当method2方法执行完后,会将栈帧2从栈顶弹出

method1方法执行完毕后,将栈帧1弹出

依次顺序直至线程被销毁。

注意点

2. 栈的线程安全问题

局部变量是线程安全的

现在我们定义如下方法:

 public static void method() {
     int a = 0;
     a++;
 }

我们在方法method中定义了一个局部变量a,并对其执行a++操作,现在假设我们有两个线程同时调用了这个方法(栈帧),Java虚拟机会将该栈帧压入各自线程的栈内存中,但由于局部变量表是线程私有的,所以两个线程在同时调用这个栈帧后,a的值仍然都为1,故局部变量是线程安全的

方法参数和方法返回值不是线程安全

由于方法的参数和返回值均可被外部方法所引用,故在某个线程下某个方法可以更改另外一个方法的参数和返回值,故方法参数和方法返回值不是线程安全的

3. 栈内存溢出

由于程序执行时,虚拟机给每个栈分配的栈内存空间是固定的,所以在一些情况下有可能出现栈内存空间不足,导致溢出的情况,一般有两种情况可能导致栈内存溢出

现在我们来解释一下什么时候会出现栈帧过多导致栈内存溢出,我们来假设某一个栈的内存空间大小是1024kb,现在有四个栈帧,每个栈帧的大小均为300kb,而 300 * 4 = 1200kb, 而 1200 > 1024 ,很显然,现在这四个栈帧合起来的大小已经超过了这个栈的内存空间大小,这个时候就会出现栈内存溢出,也就是会报java.lang.StackOverflowError这个错误。

到此这篇关于Java 虚拟机栈详解分析的文章就介绍到这了,更多相关Java 虚拟机栈内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文