数据结构 [栈]

栈概念


栈(stack)又名堆栈,它是一种运算受限的线性表。限定仅在表尾进行插入和删除操作的线性表。这一端被称为栈顶,相对地,把另一端称为栈底。向一个栈插入新元素又称作进栈、入栈或压栈,它是把新元素放到栈顶元素的上面,使之成为新的栈顶元素;从一个栈删除元素又称作出栈或退栈,它是把栈顶元素删除掉,使其相邻的元素成为新的栈顶元素。

——百度百科《栈》

#yyds干货盘点# jvm——虚拟机栈_jvm

这是一个简易的栈工作图,可以把它理解为手枪的弹夹,每次装弹的时候越先装入的子弹会在弹夹越下面,射击的时候会先射出最后装入的子弹,依此类推,最先装入的子弹最后射出。|第一个进入栈内的数据出栈就是最后一个,总结: 栈始终保持着先进后出,后进先出的原则。


虚拟机栈

概念


1、java程序中每个方法被执行的时候,jvm都会同步创建一个栈帧(可以理解为弹夹中的子弹)用于存储参数局部变量动态连接操作数栈方法出口等信息,可以理解为每个方法运行时需要的内存。

2、每一个方法被调用直至执行完毕的过程,就会对应着一个栈帧在jvm中完成入栈出栈的过程。

3、虚拟机栈程序计数器一样是线程私有的生命周期于线程相同,也可以说虚拟机栈线程运行时需要的内存空间

4、每个线程只能有一个活动栈帧,对应着当前正在执行的那个方法。


示例

public static void main(String[] args){
test1();
}

private static void test1(){
test2();
}

private static void test2(){
System.out.println("测试栈帧");
}

使用 debug 模式启动,在输出那里打个断点,然后查看控制台可以看到对应的方法名字。

这里时先调用的 test1() ,后调用的 test2() ,栈先进后出,后进先出的原则。test1方法在test2方法下面,最后执行释放时 test2栈帧会先释放 test1栈帧 会后释放。

我们通常写业务代码会调用各种方法,那么会在虚拟机栈中产生许多栈帧,栈帧中又存储着数据,那么到达一定程度时会产生内存溢出的问题。

#yyds干货盘点# jvm——虚拟机栈_jvm_02

内存溢出

原因:

1、 栈证过多导致内存溢出

2、 栈证过大导致内存溢出(一般不会出现)

栈帧过多示例

    private static int count;
public static void main(String[] args){
try{
method1();
}catch(Throwable e){
e.printStackTrace();
Sytem.out.println(count);
}
}

private static void method1(){
count++;
method1();
}

运行以上代码会报 java.lang.StackOverflowError 栈内存溢出错误。

#yyds干货盘点# jvm——虚拟机栈_jvm_03