Java 虚拟机栈详解分析
作者:小小奶酪可笑可笑 发布时间:2021-08-29 10:04:55
Java虚拟机栈
1. 定义
栈:线程运行时需要的内存空间,一个栈存在多个栈帧。栈具有先入后出,后入先出的特点。
栈帧:每个方法运行时需要的内存(局部变量表、操作数栈、动态链接和方法返回值等信息。),每次调用一个方法,便会将栈帧压入栈中,方法执行完毕将栈帧从栈顶压出
活动栈帧:指在栈顶的栈帧,既正在调用的方法,每个线程只能有一个活动栈帧,对应着该线程正在调用的那个方法
现在我们用代码来演示一下Java虚拟机如何将栈帧压入及压出栈中
public class Main {
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;
}
}
当我们运行Main函数时,jvm首先将栈帧Main压入栈中,此视栈结构如图所示
Main函数体中调用了method1方法,此时便会将栈帧1压入栈中
method1方法体中调用了method2方法,这时jvm会将栈帧2压入栈结构中,需要注意的是,前面我们提到了栈帧由 “局部变量表、操作数栈、动态链接和方法返回值”等信息组成,method2方法中拥有a,b两个参数以及局部变量c和方法返回值
当method2方法执行完后,会将栈帧2从栈顶弹出
method1方法执行完毕后,将栈帧1弹出
依次顺序直至线程被销毁。
注意点
由于每个栈帧都会在方法调用完毕后被弹出,因此栈内存不需要进行垃圾回收
每个栈都是线程私有的,每个线程在创建的时候都会创建一个虚拟机栈,而由于物理内存是固定的,栈内存划分得越大,可分配的线程数就越少
2. 栈的线程安全问题
局部变量是线程安全的
现在我们定义如下方法:
public static void method() {
int a = 0;
a++;
}
我们在方法method中定义了一个局部变量a,并对其执行a++操作,现在假设我们有两个线程同时调用了这个方法(栈帧),Java虚拟机会将该栈帧压入各自线程的栈内存中,但由于局部变量表是线程私有的,所以两个线程在同时调用这个栈帧后,a的值仍然都为1,故局部变量是线程安全的
方法参数和方法返回值不是线程安全
由于方法的参数和返回值均可被外部方法所引用,故在某个线程下某个方法可以更改另外一个方法的参数和返回值,故方法参数和方法返回值不是线程安全的
3. 栈内存溢出
由于程序执行时,虚拟机给每个栈分配的栈内存空间是固定的,所以在一些情况下有可能出现栈内存空间不足,导致溢出的情况,一般有两种情况可能导致栈内存溢出
栈帧过大(较少出现)
栈帧过多(一般出现在递归时。没有正确设置递归出口)
现在我们来解释一下什么时候会出现栈帧过多导致栈内存溢出,我们来假设某一个栈的内存空间大小是1024kb,现在有四个栈帧,每个栈帧的大小均为300kb,而 300 * 4 = 1200kb, 而 1200 > 1024 ,很显然,现在这四个栈帧合起来的大小已经超过了这个栈的内存空间大小,这个时候就会出现栈内存溢出,也就是会报java.lang.StackOverflowError这个错误。
来源:https://blog.csdn.net/qq1104380920/article/details/121199089


猜你喜欢
- Assets文件介绍assets文件夹里面的文件都是保持原始的文件格式,需要用AssetManager以字节流的形式读取文件。 1. 先在A
- Maven的安装安装Maven之前要确保已经安装好了jdk,并且配置好了环境变量JAVA_HOME。具体安装步骤如下:1. 从ap
- SQLite是Android自带的关系型数据库,是一个基于文件的轻量级数据库。Android提供了3种操作数据的方式,SharedPrefe
- 递归出现栈溢出stackoverflow递归是个不断回调方法的过程,使方法一遍遍的压入栈中,递归次数多了,栈满了也就溢出了。默认的栈大小是1
- 单链表:每个数据是以节点的形式存在的每个节点分为数据域和指针域数据域中保存该节点的数据指针域中保存指向下一个节点的指针实现思路:节点类Sin
- 日期显示和选择类库,可以用来选择一段连续的和多个不连续的日期,具体的UI完全抽象出来了,可以高度自定义(GITHUB地址)支持的功能:1、选
- 前言不久之前,部门进行了一次代码评审。代码整体比较简单,该吹B的地方都已经吹过了,无非是些if else的老问题而已。当翻到一段定时任务的一
- 本文实例讲述了C#推送信息到APNs的方法。分享给大家供大家参考。具体实现方法如下:class Program{ public
- 也许很多朋友在学习NIO的时候都会感觉有点吃力,对里面的很多概念都感觉不是那么明朗。在进入Java NIO编程之前,我们今天先来讨论一些比较
- RestTemplate简介Spring RestTemplate 是 Spring 提供的用于访问 Rest 服务的客户端,RestTem
- 在日常工作中,经常需要不同格式的图片,有时还需要进行图片格式的相互转换,本文以一个简单的小例子,简述图片格式转换的常见方法,仅供学习分享使用
- 一、概述顶部ViewPager指示器的字体变色,该效果图是这样的:大概是今天头条的app,神奇的地方就在于,切换ViewPager页面的时候
- 本文实例讲述了Java单例模式。分享给大家供大家参考,具体如下:在实际开发的时候会有一些需求,在某个类中只能允许同时存在一个对象。这时就需要
- 【前言】面向资源的 Restful 风格的 api 接口本着简洁,资源,便于扩展,便于理解等等各项优势,在如今的系统服务中越来越受欢迎。.n
- bean.xml文件p标签使用报错The prefix "p" for attribute "p:某属性&qu
- 一、 * 与过滤器在讲Spring boot之前,我们先了解一下过滤器和 * 。这两者在功能方面很类似,但是在具体技术实现方面,差距还是比较
- 本文实例讲述了Android开发之DatePicker和TimePicker实现选择日期时间功能。分享给大家供大家参考,具体如下:DateP
- java中的set接口有如下的特点:不允许出现重复元素;集合中的元素位置无顺序;有且只有一个值为null的元素。因为java中的set接口模
- 引言这里实现一个简单的图片上传功能,主要是熟悉这个文件上传的交互流程。关于更复杂的文件上传,如大文件的切片上传、断点续传等,这里不做过多介绍
- 项目需求为APP的使用单位有很多部门,各个部分的业务也是独立的,所以开发的APP中如果把所有的模块都显示出来然后再做权限分配,会显得屏幕全是