虚拟机栈
回忆栈的数据结构
调用第一个方法时,会为其分配一个栈帧空间,并且把其压入栈内,当方法执行完时,就会释放栈帧空间
定义
- 每个线程运行时所需要的内存,称为虚拟机栈
- 每个栈由多个栈帧组成,对应者每次方法调用时所占用的内存
- 每个线程只能有一个活动栈帧,对应着当前正在执行的那个方法
/**
* 演示栈帧
**/
public class Demo1_1 {
public static void main(String[] args){
method1();
}
private static void method1(){
method2(1,2);
}
private static int method2(int a, int b){
int c = a + b;
return c;
}
}
问题辨析
-
垃圾回收是否涉及栈内存?
不设计,栈帧内存在每次方法调用结束后,都会自动释放,根本不需要垃圾回收来管理栈内存,垃圾回收只会回收堆内存中的无用对象。
-
栈内存分配越大越好吗?
为栈内存指定大小:-Xss size。例如:-Xss1m、-Xss1024k 栈内存变大了,只会增强方法调用的运行效率,但是线程数量会减少。不建议设置过大的栈内存。
-
方法内的局部变量是否线程安全?
- 如果方法内局部变量没有逃离方法的作用访问,它是线程安全的。
- 如果局部变量引用了对象,并逃离方法的作用方法,需要考虑线程安全。
栈内存溢出
- 栈帧过多导致栈内存溢出
- 栈帧过大导致栈内存溢出
/**
* 演示栈内存溢出
* 结果:抛出异常:java.lang.StackOverflowError
* -Xss256k
**/
public class Demo1_1 {
private static int count;
public static void main(String[] args){
try{
method1();
}catch(Throwable e){
e.printStackTrace();
System.out.println(count);
}
}
private static void method1(){
count++;
method1();
}
}
线程运行诊断
案例1:cpu占用过多
定位
-
用top命令定位哪个进程对cpu的占用过高
-
ps -H -eo pid,tid,%cpu | grep 进程id(用ps命令进一步定位是哪个线程引起的cpu占用过高)
-
jstack 进程id
可以根据进程id找到有问题的线程,进一步定位到问题代码的源码行号