简介

Java栈是一块线程私有的内存空间。java堆和程序数据相关,java栈就是和线程执行密切相关的,线程的执行的基本行为是函数调用,每次函数调用的数据都是通过java栈来传递的。

Java栈与数据结构中的stack有着类似的含义,都是先进先出的数据结构,只支持出栈和入栈操作。java栈中保存的主要内容为栈帧。每一次函数调用都有一个对应的栈帧被压入java栈。每一个函数调用结束,都会有一个栈帧被弹出java栈。当前正在执行的函所对应的栈帧位于当前栈的栈顶,它保存当前函数的局部变量,中间运算结果等数据。

当函数返回时,栈帧从java栈中被弹出。java方法有两种返回的方式,
* 一种是正常的函数返回;
* 一种是异常抛出。
这两种方式都会导致栈帧被弹出。

一个栈帧中至少要包含局部变量表、操作数栈和帧数据几个部分。

由于每个函数调用都会生成对应的栈帧,从而占用一定的栈空间,因此,如果栈空间不足,那么函数调用自然就无法继续进行下去,特别是递归算法特别需要耗费栈帧。当请求的栈的深度大于最大的可用栈的深度时,系统就会抛出StackOverflowError栈溢出错误。

两大著名的程序猿交流网站的名称的由来,StackOverflowSegmentFault,就是这么来的。

程序实验

下面的例子通过递归调用,打印出我的电脑中可以用的最大的栈深。

public class PrintStackDeepth {
    private static int length=0;
    public static void recursion()
    {
    length++;
    recursion();
    }
    public static void main(String[] args) {
    try {
        recursion();
    } catch (Throwable ex) {
        System.out.println(length);
    }
    }
}

运行说明

再制定当前程序运行的最大内存的情况下,不同的-Xss值会获得不同的栈深

Java程序中,每个线程都有自己的Stack Space。这个Stack Space不是来自Heap的分配。所以Stack Space的大小不会受到-Xmx和-Xms的影响,这2个JVM参数仅仅是影响Heap的大小。
Stack Space用来做方法的递归调用时压入Stack Frame。所以当递归调用太深的时候,就有可能耗尽Stack Space,爆出StackOverflow的错误。Stack Space的大小随着OS,JVM以及环境变量的大小而发生变化。一般说来默认的大小是512K。在64位的系统中,这个Stack Space值会更大。一般说来,Stack Space为128K是够用的。这时你说需要做的就是观察。如果你的程序没有爆出StackOverflow的错误,可以使用-Xss来调整Stack Space的大小为128K。(eg:-Xss128K)