深入理解Java虚拟机——运行时栈帧结构(局部变量表)

一、局部变量表的概述

  • 局部变量表(Local Variable Table)是一组变量值存储空间,用于存放方法参数和方法内部定义的局部变量。
  • 在jav程序编译为Class文件时,就在方法的Code属性的max_locals数据项中确定了该方法所需要分配的局部变量表的最大容量。
  • 局部变量表的容量以变量槽(Variable Slot)为最小单位,虚拟机规范中并没有明确指明一个Slot应占用的内存空间大小,只是很有导向性的说到每个Slot都应该存放一个boolean、byte、char、short、int、float、reference或renturnAddress类型的数据,这8中数据类型。
  • 为了尽可能的节省栈帧空间,局部变量表中的Slot是可以重用的。

二、reference类型的概述

  • reference类型表示对一个对象实例的引用。
  • 虚拟机实现至少都应当能通过这个引用做到两点:
    (1)、从此引用中直接或间接地查找到对象在Java堆中的数据存放的起始地址索引。
    (2)、从此引用中直接或间接地查找到对象所属数据类型在方法区中的存储的数据类型。

三、renturnAddress类型的概述

  • renturnAddress类型目前已经很少见了,它是为了字节码指令jsr、jsr_w和ret服务的,指向了一条字节码指令的地址。

四、局部变量表中Slot槽复用对垃圾回收的影响

4.1、局部变量表中Slot槽复用对垃圾回收的影响(一)

  • 源码

    public class Test {
        public static void main(String[] args) {
            byte[] a = new byte[64 * 1024 * 1024];
            System.gc();
        }
    }
    
  • 输出结果
    在这里插入图片描述

  • 总结
    向内存中填充了64MB的数据,虚拟机运行参数中添加“-verbose:gc”,发现System.gc()运行后并没有回收这64MB的内存,因为在执行System.gc()时,变量a还处于作用于内,虚拟机自然不敢回收a的内存。

4.2、局部变量表中Slot槽复用对垃圾回收的影响(二)

  • 源码

    public class Test {
        public static void main(String[] args) {
            {
                byte[] a = new byte[64 * 1024 * 1024];
            }
            System.gc();
        }
    }
    
  • 输出结果
    在这里插入图片描述

  • 总结
    加入了花括号之后,a变量的作用域被限制在花括号内,从代码逻辑上讲,在执行System.gc()的时候,a已经不可能在被访问了,但运行接口还是有64MB的内存没有被回收。
    因为代码虽然已经离开了a的作用域,但在此之后,没有任何对局部变量表的读写操作,a原本所占用的Slot还没有被其他变量所复用,所以作为GC Roots一部分的局部变量表仍然保持这对它的关联

4.3、局部变量表中Slot槽复用对垃圾回收的影响(三)

  • 源码

    public class Test {
        public static void main(String[] args) {
            {
                byte[] a = new byte[64 * 1024 * 1024];
            }
            int b =0;
            System.gc();
        }
    }
    
  • 输出结果
    在这里插入图片描述

  • 总结
    从输出结果看,这次内存真的被正确回收了。说明手动将其设置为null值的操作在某系情况下确实是有用的。

4.4、总结

  • 示例中a变量能否被回收的根本原因是:局部变量表中的Slot是否还存有关于a数组对象的引用。
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
Java虚拟机(JVM)是Java程序的运行环境,它负责将Java字节码转换为可执行的机器码并执行。深入理解Java虚拟机涉及了解JVM的工作原理、内存管理、垃圾回收、类加载机制等方面的知识。 首先,JVM的工作原理是通过解释器或即时编译器将Java字节码转换为机器码并执行。解释器逐条执行字节码指令,而即时编译器将字节码转换为本地机器码,以提高程序的执行效率。 其次,内存管理是JVM的重要任务之一。JVM将内存分为不同的区域,包括堆、栈、方法区等。堆用于存储对象实例,栈用于存储局部变量和方法调用信息,方法区用于存储类的信息。JVM通过垃圾回收机制自动回收不再使用的对象,释放内存空间。 此外,类加载机制也是深入理解JVM的关键内容之一。类加载是将类的字节码加载到内存中,并进行验证、准备、解析等操作。类加载器负责查找并加载类的字节码,而类加载器之间存在着父子关系,形成了类加载器层次结构。 还有其他一些与性能优化、调优相关的内容,如即时编译器的优化技术、垃圾回收算法的选择等,也是深入理解Java虚拟机的重要方面。 总的来说,深入理解Java虚拟机需要对JVM的工作原理、内存管理、垃圾回收、类加载机制以及性能优化等方面有较深入的了解。掌握这些知识可以帮助开发人员编写出更高效、稳定的Java程序。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小志的博客

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值