【JVM基础04】——组成-什么是虚拟机栈?


1- 引言:虚拟机栈

1-1 虚拟机栈是什么?(What)

  • ** 虚拟机栈是每个线程独有的:**Java Virtual Machine Stacks (Java虚拟机栈),每个线程运行时候所需要的内存称为虚拟机栈,是先进后出的。栈内存也是线程安全的(因为其是每个线程独有的)。
    • 假设有栈帧来了,其会压入栈底,再有栈帧来了其会依次压入。
  • **栈帧: **每个栈由多个栈帧(frame)组成,对应着每次方法调用时所占用的内存
  • **活动栈帧:**每个线程只能有一个活动栈帧,对应着当前正在执行的方法

image.pngimage.png

1-2 为什么用虚拟机栈?虚拟机栈的作用 (Why)

  1. 方法调用管理:
  • 每个方法调用都会在虚拟机栈中创建一个新的栈帧,栈帧中包含了方法的局部变量、操作数栈、动态链接和方法返回地址等信息。通过这种机制,虚拟机能够正确地执行方法调用和返回操作。
  1. 局部变量存储:
  • 方法中的局部变量会存储在对应的栈帧中。由于栈帧是线程私有的,因此局部变量是线程安全的。

2- ⭐核心:栈的常见问题(How)

2-1 方法内的局部变量是否线程安全?

线程内的局部变量是否线程安全,取决于该变量是否被多个线程共享使用
image.png
线程安全的局部变量

  • 在方法 m1 中,StringBuilder sb 是一个局部变量,仅在方法 m1 内部使用。由于每个线程调用 m1 时都会创建自己独立的 sb 变量,因此 m1 方法中的局部变量 sb 是线程安全的。
线程不安全的局部变量
  • 在方法 m2 中,StringBuilder sb 作为参数传递进来,可能会被多个线程同时访问。图中显示在 main 方法中,一个新线程会调用 m2 方法并传入 sb 变量。这种情况下,sb 变量被多个线程共享使用,因此 m2 方法中的局部变量 sb 是线程不安全的。
  • 在方法 m3 中,StringBuilder sb 虽然是在方法内部创建的局部变量,但方法返回了这个变量的引用。此时,外部方法(例如 main 方法)可以共享和修改这个返回的 sb 变量。如果多个线程调用 m3 方法并使用返回的 sb 变量,也会导致线程不安全。

结论

  • 线程安全:当局部变量在方法内部使用,并且没有逃离方法的作用范围,它是线程安全的。
  • 线程不安全:如果是局部变量引用了对象,并逃离方法的作用范围(当局部变量通过参数传递或者作为返回值返回),导致可能被多个线程共享使用,此时是线程不安全的。

2-2 什么情况会导致栈内存溢出?

① 栈帧过多导致栈内存溢出,典型的问题:递归调用
image.png
② 栈帧过大导致栈内存溢出

  • 局部变量过多:当一个方法中定义了过多的局部变量,每个局部变量都需要在栈中分配空间,导致栈帧过大。如果栈帧大小超过了虚拟机栈的最大限制,将会导致栈内存溢出。
  • 大对象的局部变量:如果方法中包含大对象作为局部变量,这些对象会占用大量的栈空间,导致栈帧过大,进而可能导致栈内存溢出。

2-3 栈和堆的区别?

①用途和存储内容不同

  • 栈内存:用于存储局部变量和方法调用。每当一个方法被调用时,都会在栈中创建一个新的栈帧,用于存储该方法的局部变量、操作数栈、动态链接和方法返回地址等信息。
  • 堆内存:用于存储所有的 Java 对象和数组。堆是一个被所有线程共享的内存区域,用于存放在运行时创建的对象和数组。

②线程安全性:

  • 栈内存:是线程私有的,每个线程都有自己的栈,因此栈内存是线程安全的,不需要考虑多线程并发访问的问题。
  • 堆内存:是线程共享的,多个线程可以访问同一个对象,因此需要考虑线程安全问题,可能需要同步机制来避免数据竞争。

③内存管理

  • 栈内存:由系统自动分配和释放。每当方法调用时,栈帧自动分配;方法结束时,栈帧自动销毁,内存释放。
  • 堆内存:由垃圾回收器(GC)管理。Java 程序中对象的分配和释放由垃圾回收器负责,当对象不再被引用时,GC 会自动回收这些对象所占用的内存。

④存储大小:

  • 栈内存:通常较小且固定,每个线程有一个独立的栈,栈大小在程序启动时由虚拟机设置。
  • 堆内存:通常较大且可动态扩展,整个 Java 应用程序共享一个堆内存区域,堆大小可以在启动时通过 JVM 参数进行配置。

⑤内存溢出:

  • 栈内存:栈的内存不足会抛出 StackOverflowError,常见原因是递归调用过深或方法调用层次过多,导致栈帧数量过多。
  • 堆内存:堆的内存不足会抛出 OutOfMemoryError,常见原因是创建了过多的对象,或对象占用的内存过大,导致堆内存耗尽。

3- 小结:

3-1 什么是虚拟机栈?

在这里插入图片描述

3-2 垃圾回收是否涉及栈内存?

在这里插入图片描述

3-3 栈内存分配越大越好吗?

在这里插入图片描述

3-4 方法内的局部变量是否线程安全?

在这里插入图片描述

3-5 什么情况会导致栈内存溢出?

在这里插入图片描述

3-6 栈和堆的区别?

在这里插入图片描述


  • 6
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值