资讯专栏INFORMATION COLUMN

一次有趣的局部变量GC

alogy / 2968人阅读

摘要:前言最近在看实战虚拟机发现书上的一个关于局部变量表挺有意思,先上代码。主角没有分配了一块的堆空间,并使用局部变量引用这块空间然后显式进行一次。

前言

最近在看《实战Java虚拟机》, 发现书上的一个关于局部变量表GC挺有意思,先上代码。

主角 没有GC
public class Main {
    public static void reversion(){
        {
            byte[] a = new byte[6*1024*1024];
        }
        System.gc();
    }

    public static void main(String[] args) {
        reversion();
    }
}

分配了一块6MB的堆空间,并使用局部变量引用这块空间, 然后显式进行一次Full GC。

先配置一下JVM参数用于打印GC log

可以看到这块6MB的堆空间并没有被回收, 接下来加一行代码就能使得堆空间被回收。

可以GC
public class Main {
    public static void reversion(){
        {
            byte[] a = new byte[6*1024*1024];
        }
        int c = 0;
        System.gc();
    }

    public static void main(String[] args) {
        reversion();
    }
}

可以看到这6MB的空间已经被回收了,仅仅因为多了一句看似与a毫无关系的 int c = 0;

答案

借助jclasslib工具我们进一步查看函数的局部变量信息, 在此之前我们需要对代码做一点小改动再进行分析

public class Main {
    public static void reversion(){
        {
            byte[] a = new byte[6*1024*1024];
            System.out.println(a[0]);
        }
        int c = 0;
        System.gc();
    }

    public static void main(String[] args) {
        reversion();
    }
}

tips:JVM即时编译器拥有死代码消除的特性,a数组并没有被任何地方使用,即时编译器可以精简数据流,并且减少编译时间以及最终生成机器码的大小。简单的说如果a没有被使用的话会被编译成var0, 我们在本地变量表中看不到a了。

可以看到a和c在局部变量表中的索引值都是0,也就是说c重用了a在局部变量表中的槽位,从而使得a指向的堆空间能够被GC回收

栈帧中的局部变量表中的槽位是可以重用的,如果一个局部变量过了其作用域,那么在其作用域之后申明的新的局部变量就很有可能复用过期局部变量的槽位,从而达到节省资源的目的

总结

通过这个GC的小例子,切实感受到了JVM对于资源节省的严苛程度,对于作用域的细粒度把控之强大。给大家推荐我读的这本《实战Java虚拟机》,切实的一本好书,所谓好书无非两点:1.能读懂 2.有所获。同时也推荐极客时间的《深入拆解虚拟机》,多路学习,兼听则明。

最后打个小广告~

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/71928.html

相关文章

  • JVM解剖公园

    摘要:为此,引入转换查找缓冲缓存最近的转换记录。这个优化技术,可以看到将原本对对象的字段访问,替换为一个局部变量的访问。当所有线程都在已知的位置停止的时候,被认为是到达了安全点。检查安全点请求的代码 showImg(https://segmentfault.com/img/bVbwfcz?w=1024&h=576); 1、JVM锁粗化和循环原文标题:JVM Anatomy Quark #1:...

    imingyu 评论0 收藏0
  • JAVA GC垃圾回收(及一次内存泄漏处理)

    摘要:垃圾回收及一次内存泄漏处理内存分布上图展示了的架构图,本篇我们主要关注,运行时数据区。但是垃圾回收并不能百分百保证不会出现内存泄漏,所以了解垃圾回收,对于我们遇到内存泄漏时能更加清晰的分析原因,也能帮助我们写出更加安全,可靠的程序。 [toc] JAVA GC垃圾回收(及一次内存泄漏处理) showImg(https://segmentfault.com/img/remote/1460...

    RaoMeng 评论0 收藏0
  • 对象

    摘要:入队列,即表示当前对象已回收。时,清空对象的属性即执行,再将对象加入该对象关联的中。当一个被掉之后,其相应的包装类对象会被放入中。原因是编译程序实现上的困难内部类对象的生命周期会超过局部变量的生命期。 一个类的静态成员在类的实例gc后,不会销毁。 对象引用强度 强引用Strong Reference 就是指在代码之中普遍存在的,类似:Object objectRef = new Obe...

    nanfeiyan 评论0 收藏0

发表评论

0条评论

alogy

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<