jvm内存部分——虚拟机栈

在这里插入图片描述

栈的特点

栈(stack)是一种常用的数据结构,遵从先入后出的规则

虚拟机栈与栈帧

在这里插入图片描述
当线程运行调用方法时,会给方法划分一段栈帧空间,如方法1划分一个栈帧1,然后压入栈内进行运行,运行完后出栈并释放内存。
在这里插入图片描述

当方法1中调用了方法2时,则会划分一个栈帧2的空间压入栈并运行,方法2运行完后返回值交给方法1,栈帧2出栈释放空间,然后运行方法1。
在这里插入图片描述

虚拟机栈定义

Java Virtual Machine Stacks ——Java虚拟机栈

  • 每个线程运行所需要的内存称为虚拟机栈
  • 每个栈由多个栈帧(Frame)组成,对应着每次方法调用时所占用的内存
  • 每个线程只能有一个活动栈帧,对应着当前正在执行的那个方法
//演示虚拟机栈运行过程
public class JvmStacks {
    public static void main(String[] args) {
        method1();
    }
    public static void method1(){
        method2(1,2);
    }
    static int method2(int a,int b){
        int c=a+b;
        return c;
    }
}

在这里插入图片描述

相关问题辨析

1、垃圾回收是否涉及栈内存
不需要,栈内存只是一次次方法调用产生的栈帧内存,而栈帧内存在运行完后会自动释放。垃圾回收主要是针对堆内存的无用对象。
2、栈内存分配越大越好吗?
分配栈内存指令:
-Xss size
Sets the thread stack size (in bytes). Append the letter k or K to indicate KB, m or M to indicate MB, and g or G to indicate GB. The default value depends on the platform:

Linux/x64 (64-bit): 1024 KB

macOS (64-bit): 1024 KB

Oracle Solaris/x64 (64-bit): 1024 KB

Windows: The default value depends on virtual memory

The following examples set the thread stack size to 1024 KB in different units:
来自https://docs.oracle.com/en/java/javase/11/tools/java.html

-Xss1m
-Xss1024k
-Xss1048576

内存并不是越大越好,物理内存是一定的,当栈的内存大时,就会导致线程数量减少,栈内存大只是可以调用更多的方法,分配更多的栈帧,不会增加你的运行效率。
3、方法内的局部变量是否线程安全?

public class JvmStacks {
    public static void main(String[] args) {
        StringBuilder sb=new StringBuilder();
        sb.append(1);
        sb.append(2);
        sb.append(3);
        //这种创建方法适用于jdk1.8及以上
        new Thread(() ->{
            method2(sb);
        }).start();
    }
    
    public static void method1(){
        StringBuilder sb=new StringBuilder();
        sb.append(1);
        sb.append(2);
        sb.append(3);
        System.out.println(sb.toString());
    }
    static void method2(StringBuilder sb){
        sb.append(4);
        sb.append(5);
        sb.append(6);
        System.out.println(sb.toString());
    }
    static String method3(){
        StringBuilder sb=new StringBuilder();
        sb.append(7);
        sb.append(8);
        sb.append(9);
        return sb.toString();
    }
}
  • 调用方法1时:
    在这里插入图片描述
    调用方法1时两个线程分别产生一个栈帧来存方法1,同时新建一个sb,互不影响。

  • 调用方法2:
    在这里插入图片描述
    调用方法2时有一个main方法中的全局变量sb,线程1和线程2都得读取这个sb并写回sb。

  • 调用方法3
    调用方法3时,虽然没引用对象,但有返回值,可能有别的方法获得这个返回值,所以不是线程安全的;

所以:

  • 如果方法内局部变量没有逃离方法的作用范围,它是线程安全的
  • 如果是局部变量引用了对象,并逃离方法的作用的作用范围,需要考虑线程安全
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值