一、虚拟机栈(VM Stack)
1.1)什么是虚拟机栈
虚拟机栈是用于描述java方法执行的内存模型。
每个java方法在执行时,会创建一个“栈帧(stack frame)”,栈帧的结构分为“局部变量表、操作数栈、动态链接、方法出口”几个部分(具体的作用会在字节码执行引擎章节中讲到,这里只需要了解栈帧是一个方法执行时所需要数据的结构)。我们常说的“堆内存、栈内存”中的“栈内存”指的便是虚拟机栈,确切地说,指的是虚拟机栈的栈帧中的局部变量表,因为这里存放了一个方法的所有局部变量。
方法调用时,创建栈帧,并压入虚拟机栈;方法执行完毕,栈帧出栈并被销毁,如下图所示:

1.2)虚拟机栈的特点
虚拟机栈是线程隔离的,即每个线程都有自己独立的虚拟机栈。
1.3)虚拟机栈的StackOverflowError
若单个线程请求的栈深度大于虚拟机允许的深度,则会抛出StackOverflowError(栈溢出错误)。
函数调用,代码见下:
1 /**
2 * java栈溢出StackOverFlowError
3 * JVM参数:-Xss128k
4 * Created by chenjunyi on 2018/4/25.
5 */
6 public class JavaVMStackSOF {
7
8 private int stackLength = -1;
9
10 //通过递归调用造成StackOverFlowError
11 public void stackLeak() {
12 stackLength++;
13 stackLeak();
14 }
15
16 public static void main(String[] args) {
17 JavaVMStackSOF oom = new JavaVMStackSOF();
18 try {
19 oom.stackLeak();
20 } catch (Throwable e) {
21 System.out.println("Stack length:" + oom.stackLength);
22 e.printStackTrace();
23 }
24 }
25
26 }设置单个线程的虚拟机栈内存大小为128K,执行main方法后,抛出了StackOverflow异常
1 Stack length:983
2 java.lang.StackOverflowError
3 at com.manayi.study.jvm.chapter2._02_JavaVMStackSOF.stackLeak(_02_JavaVMStackSOF.java:14)
4 at com.manayi.study.jvm.chapter2._02_JavaVMStackSOF.stackLeak(_02_JavaVMStackSOF.java:15)
5 at com.manayi.study.jvm.chapter2._02_JavaVMStackSOF.stackLeak(_02_JavaVMStackSOF.java:15)
6 ······1.4)虚拟机栈的OutOfMemoryError
整个虚拟机栈内存耗尽,并且无法再申请到新的内存时抛出的异常。
OutOfMemoryError,可以通过不断开启新的线程来模拟这种异常,代码如下:
1 **
2 * java栈溢出OutOfMemoryError
3 * JVM参数:-Xss2m
4 * Created by chenjunyi on 2018/4/25.
5 */
6 public class JavaVMStackOOM {
7
8 private void dontStop() {
9 while (true) {
10 }
11 }
12
13 //通过不断的创建新的线程使Stack内存耗尽
14 public void stackLeakByThread() {
15 while (true) {
16 Thread thread = new Thread(() -> dontStop());
17 thread.start();
18 }
19 }
20
21 public static void main(String[] args) {
22 JavaVMStackOOM oom = new _03_JavaVMStackOOM();
23 oom.stackLeakByThread();
24 }
25
26 }设置单个线程虚拟机栈的占用内存为2m并不断生成新的线程,最终虚拟机栈无法申请到新的内存,抛出异常:
1 Exception in thread "main" java.lang.OutOfMemoryError: unable to create new native thread二、本地方法栈(Native Method Stack)
本地方法栈的功能和特点类似于虚拟机栈,均具有线程隔离的特点以及都能抛出StackOverflowError和OutOfMemoryError异常。
不同的是,本地方法栈服务的对象是JVM执行的native方法,而虚拟机栈服务的是JVM执行的java方法。如何去服务native方法?native方法使用什么语言实现?怎么组织像栈帧这种为了服务方法的数据结构?虚拟机规范并未给出强制规定,因此不同的虚拟机实可以进行自由实现,我们常用的HotSpot虚拟机选择合并了虚拟机栈和本地方法栈。
















