JVM内存模型——详细介绍下Java虚拟机栈
java8 虚拟机规范:https://docs.oracle.com/javase/specs/jvms/se8/html/index.html
1.Java虚拟机栈的特点
- Java虚拟机栈是线程私有的,它的生命周期和线程相同。
- 虚拟机栈描述的是Java方法执行的内存模型: 每个方法在执行的同时 都会创建一个栈帧(StackFrame)用于存储局部变量表、操作数栈、动态链接、方法出口等信息。
- 不存在垃圾回收的概念, 也就是说不会内存溢出,发生OOM, 但是会出现
栈溢出 (StackOverFlow)
。 栈
解决程序的运行
问题,即 程序如何执行,或者说如何处理数据。- -Xss512k 设置栈内存大小为512k
2.名词解释
虚拟机栈中是有单位的,单位就是栈帧,一个方法一个栈帧。一个栈帧中他又要存储,局部变量,操作数栈,动态链接,出口等。
2.1栈帧
-
局部变量表:是用来存储我们临时8个基本数据类型、对象引用地址、returnAddress类型。(returnAddress中保存的是return后要执行的字节码的指令地址。)
-
操作数栈:操作数栈就是用来操作的,例如代码中有个 i = 6+10,他在一开始的时候就会进行操作,读取我们的代码,进行计算后再放入局部变量表中去。
-
动态链接:假如我方法中,有个 service.add()方法,要链接到别的方法中去,这就是动态链接,存储链接的地方。
-
出口:出口是什呢,出口正常的话就是return,不正常的话就是抛出异常落。
-
在虚拟机栈里面, 同一时间点上只能有
一个活动的栈帧
, 即栈顶
的栈帧(当前正在执行的方法)。 -
不同线程中所包含的栈帧是不允许存在相互引用的,即不可能在一个栈帧之中引用另外一个线程的栈帧。
3.虚拟机栈的异常
Java 虚拟机规范允许Java栈的大小是动态的或者是固定不变的:
- 如果采用固定大小的Java虚拟机栈,**那每一个线程的Java虚拟机栈可以在线程创建的时候独立设置该线程的栈容量。**如果线程请求分配的栈容量超过Java虚拟机栈允许的最大容量,Java虚拟机将会抛出一个StackoverflowError异常。
- 如果Java虚拟机栈可以动态扩展,并且在尝试扩展的时候无法申请到足够的内存,或者在创建新的线程时没有足够的内存去创建对应的虚拟机栈,那Java虚拟机将会抛出一个 OutofMemoryError 异常。
(该OOM是由于扩展栈容量时, 没有足够的内存使用)
4.常见问题
一个方法调用另一个方法,会创建很多栈帧吗?
答:会创建。如果一个栈中有动态链接调用别的方法,就会去创建新的栈帧,栈中是由顺序的,一
个栈帧调用另一个栈帧,另一个栈帧就会排在调用者下面
栈指向堆是什么意思?
栈指向堆是什么意思,就是栈中要使用成员变量怎么办,栈中不会存储成员变量,只会存储一个应
用地址
递归的调用自己会创建很多栈帧吗?
答:递归的话也会创建多个栈帧,就是在栈中一直从上往下排下去