1. 虚拟机栈
虚拟机栈定义:线程运行所需要的内存空间
虚拟机栈帧定义:每个方法运行时所需的内存空间,方法中包括成员变量和局部变量等
— 每个栈由多个栈帧组成,对应着每次调用方法时所用的内存
— 每个线程只能由有一个活动栈帧,对应着当前正在执行的方法
2. DEMO演示
由于每个栈帧保存一个方法,所以采用方法递归调用的Debug演示:
public class helloworld {
private static int method1(int a){
return a;
}
private static int method2(int a,int b){
return method1(a)+method1(b);
}
public static void main(String[] args) {
int a = 10;
System.out.println(method2(10,22));
}
}
3. 问题辨析
(1)垃圾回收是否涉及栈内存?
不会。栈内存是方法调用产生的,方法调用结束后会弹出栈
(2)栈内存分配越大越好吗?
不是。因为物理内存是一定的,栈内存越大,可以支持更多的递归调用,但是可执行的线程数就会越来越小
(3)方法的局部变量是否线程安全
如果方法内部变量没有逃离方法的作用域,因为它始终在虚拟机栈中,它是线程安全的
如果是局部变量引用了对象,并逃离了方法作用范围,那就要考虑线程安全问题
判断是否逃离方法作用范围:查看入参和返回对象有没有涉及到局部变量
3. 栈内存溢出
异常:Java.lang.stackOverflowError
原因:
— 虚拟机中,栈帧过多(无限递归)
— 每个栈帧内存过多
演示案例:
Xss:该参数规定了每个线程虚拟机栈的大小
在VM options编辑栏中填写——Xss:256k
4. 线程运行诊断——cpu占用内存过多
解决方案:Linux运行环境中运行某些程序的时候,可能导致CPU的占用过高,这时需要定位占用CPU过高的原因
top:查看哪个进程占用CPU过高
ps -H -eo pid(进程id),tid(线程id),%cpu | grep 进程号:进一步查看哪个线程占用CPU过高
jstack 进程id :可以查看进程中的线程id,刚才通过ps命令看到的tid来对比定位,注意jstack查找出的线程id是16进制的(nid=0x),需要转换