JVM基础篇-虚拟机栈
定义
Java Virtual Machine Stacks (Java 虚拟机栈)
- 每个线程运行时所需要的内存,称为虚拟机栈
- 每个栈由多个栈帧(Frame)组成,对应着每次方法调用时所占用的内存
- 每个线程只能有一个活动栈帧,对应着当前
正在执行
的那个方法
栈帧组成部分:方法参数、局部变量、返回地址
执行流程
方法执行时执行压栈操作,如果该方法调用了其他方法,其他方法被调用时执行压栈操作,方法执行完成后执行出栈操作
问题辨析
垃圾回收是否涉及栈内存?
答:不涉及,当方法执行完成后会执行出栈操作,对应的栈内存会被自动释放
栈内存分配越大越好吗?
答:不是,栈内存的越大只会使得方法递归调用的次数增大,但是如果栈内存越大,则意味着每个线程占用的内存越大,而可同时运行的线程数则会变少
📌指定栈内存大小
-Xss:
- 如果不设置,在Linux/MacOS中默认为1024KB,Windows系统则依赖于虚拟内存的大小
方法内的局部变量是否线程安全?
- 如果方法内局部变量没有逃离方法的作用访问,它是线程安全的
- 如果是局部变量引用了对象,并逃离方法的作用范围,需要考虑线程安全,如果方法参数或返回值为基本类型,则依然线程安全
package com.vmware.stack;public class Demo1 {public static void main(String[] args) {StringBuilder sb = new StringBuilder();sb.append(1);sb.append(2);sb.append(3);new Thread(() -> {m2(sb);}).start();}/*** @apiNote 该方法中StringBuild线程安全,因为外部无法方法*/public static void m1() {StringBuilder stringBuilder = new StringBuilder();stringBuilder.append(1);stringBuilder.append(2);stringBuilder.append(3);System.out.println(stringBuilder.toString());}/*** @param builder* @apiNote 该方法线程不安全,因为StringBuild可能有其他线程访问*/public static void m2(StringBuilder builder) {builder.append(1);builder.append(2);builder.append(3);System.out.println(builder.toString());}/*** @apiNote 该方法线程不安全,可能有其他线程访问返回值进行修改* @return*/public static StringBuilder m3() {StringBuilder builder = new StringBuilder();builder.append(1);builder.append(2);builder.append(3);return builder;}
}
栈内存溢出
- 栈帧过多导致栈内存溢出
- 方法递归调用
- 部分第三方类库溢出,例如json序列化循环依赖
- 栈帧过大导致栈内存溢出