虚拟机栈
虚拟机栈是,它。每个线程在创建时都会创建一个虚拟机栈,它由多个栈帧组成,每个栈帧对应一个方法的调用和执行。栈帧中包含了局部变量表、操作数栈、动态链接、方法出口等信息,这些信息是方法执行过程中的各种数据。虚拟机栈遵循先进后出的原则,当一个方法被调用时,就会创建一个新的栈帧并压入栈顶,当一个方法执行结束时,就会弹出栈顶的栈帧并返回结果。虚拟机栈的大小可以是固定的或者动态扩展的,如果栈的深度超过了虚拟机允许的最大深度,就会抛出StackOverflowError异常;如果在扩展栈时无法申请到足够的内存,就会抛出OutOfMemoryError异常。虚拟机栈是线程私有的,它与线程的生命周期同步,不会存在垃圾回收问题。12345
栈: 先进后出
栈帧: 每个方法运行时需要的内存: 参数,局部变量,返回地址
也就是包含了 局部变量表、操作数栈、动态链接、方法出口等信息
(栈帧就是虚拟机栈中的一个元素,先进后出)
(类似java方法栈中的方法)
活动栈帧:每个线程只能有一个活动栈帧,对应正在执行的方法
虚拟机栈: Java虚拟机中的一种数据结构
线程运行时需要的内存空间,不同的线程不同,用于存储每个线程执行的方法的信息
栈由多个栈帧组成,每个栈帧对应一个方法的调用和执行
Java Virtual Machine Stakes(Java虚拟机栈)
每个线程运行时所需要的内存,称为虚拟机栈
每个栈由多个栈帧组成,对应着每次方法调用时所占用的内存
每个线程只能有一个活动栈帧,对应着当前正在执行的那个方法,在栈的顶部
虚拟机栈是线程私有的,它与线程的生命周期同步,不会存在垃圾回收问题
问题: 垃圾回收是否涉及栈内存?
栈内存是方法调用留下的栈帧内存,每次方法调用结束后,会被弹出栈,自动被回收
不需要垃圾回收处理
栈内存分配越大越好吗?
Linux/mac/Orache 默认栈内存是1m:1024kb
栈内存大了,只是可以支持更多次的递归方法调用,不会速度变快
而且栈内存越大,线程总数量越少
方法内的局部变量是否是线程安全?
看一个变量是否线程安全,就是看多个线程对这个变量是共享的还是私有的
如果是局部的变量,那就会存在线程自己的栈帧中,互不干扰
如果改成static修饰,共享变量,那就可能会出现线程安全问题
栈内存溢出 stackOverflowError
原因: 1栈帧过多导致栈内存溢出
例: 方法递归调用时,没有设置合适的结束条件
例: 在转json字符串的时候,两个对象互相给参数,造成溢出
2栈帧过大导致栈内存溢出
解决: 可以在设置中设置栈内存大小,如: -Xss100k
线程诊断
案例1: cpu占用过高
例: while(true){}
定位: 用top命令定位哪个线程cpu占用过高
用ps H -eo pid,tid,%cpu|grep 进程id
(用ps命令进一步定位是哪个线程cpu占用高)
jstack 进程id
(根据线程id找到有问题的线程,进一步定位问题代码行号)
用top命令查询进程在cpu中占用过高,查看pid
ps H pid , tid , %cpu | grep 命令查看线程占用
还可以用 jstack pid来查看进程里线程信息
案例2: 程序运行很长时间
例: 死锁,
定位: 用同样方式定位,其中jstack可以看到问题原因,位置