虚拟机栈
首先了解下JVM 内存
- 什么是虚拟机栈
虚拟机栈,是线程的模型,属于线程私有并与线程生命周期相同。每一个方法的执行时创建一个栈帧,用于存储局部变量表、操作数栈、动态连接、方法接口等信息,放执行过程就是栈帧在入栈和出栈过程
虚拟机栈(局部变量表)存储编译期可知基本数据类型、对象引用地址信息。局部变量表需要的内存空间在编译期完成分配,不会再改变
-
虚拟机栈模型
虚拟机栈是线程的集合,通过
-Xss(-XX:ThreadStackSize)
配置,-Xss
称为虚拟机栈(也可以理解成栈帧大小或者单个线程的大小)。一个线程有一个栈帧,栈帧存储局部变量表。栈帧深度可以理解成线程方法局部变量占据的内存大小,在编译时分配的内存,不可修改
-
虚拟机栈中OOM
发生在虚拟机栈的内存溢出,分为两种:
StackOverFlowError
: 如果线程请求的栈深度大于虚拟机允许的最大深度时发生OutOfMemeoryError
: 如果虚拟机栈内存运行动态扩展,当扩展容量无法申请到足够内存时发生。但是HotSpot 虚拟机(我们用的基本都是HotSpot 虚拟机, java -version可查看)不支持动态扩展,所以不会发生 OutOfMemeoryError 异常。
-
栈溢出分析
jstack (Stack Trace for Java) :java 自带的工具,可以生成当前线程快照,查看阻塞、死锁等,排查OOM原因。用法参看 https://blog.youkuaiyun.com/u010519674/article/details/108686793
-
解决方案
通过jvm的内存结构得出:虚拟机栈内存 = jvm内存 - 堆内存 - 方法区大小 - 程序计数器 - 本地方法栈 - 虚拟机系统占用 剩下内存为虚拟机栈内存,虚拟机栈是线程集合,虚拟机栈内存 = 栈大小(-X:ss配置) * 线程数 得出来一个结论: 内存不变时,栈内存越大,越容易发生OOM 上面关系搞清楚,方法也简单
- 增加JVM内存
- 如果是JVM内存不变时,通过减小堆内存或者
-X:ss
内存来增大线程数