关于java:JVM详解之汇编角度理解本地变量的生命周期

42次阅读

共计 2393 个字符,预计需要花费 6 分钟才能阅读完成。

简介

java 办法中定义的变量,它的生命周期是什么样的呢?是不是肯定要等到办法完结,这个创立的对象才会被回收呢?

带着这个问题咱们来看一下明天的这篇文章。

本地变量的生命周期

在类中,变量类型有类变量,成员变量和本地变量。

本地变量指的是定义在办法中的变量,如果咱们在办法中定义了一个变量,那么这个变量的生命周期是怎么样的呢?

举个例子:

public void test(){Object object = new Object();
    doSomeThingElse(){...}
}

在下面的 test 办法中,定义了一个 object 本地变量,而后又执行了一个办法。

因为在 java 中,咱们无奈间接管制对象的生命周期,对象的回收是由垃圾回收器主动进行的。

通常来说这个 object 对象会维持到整个 test 执行完结才会被回收。

当初咱们思考一个非凡的状况,如果 doSomeThingElse 这个办法是一个 while 循环,并且永远不会完结,那么这个创立进去的 object 对象会不会被回收呢?还是始终都存在内存中?

先说咱们的论断,JVM 十分智能,能够检测进去这种状况,将 object 对象进行回收。

举例说明

为了可能更好的阐明问题,咱们自定义一个 Test 对象,并在其创立和被回收之前打印相应的信息。

    public static class Test {public Test() {System.out.println("创建对象" + this);
       }

       public void test() {System.out.println("测试对象" + this);
       }

       @Override
       protected void finalize() throws Throwable {System.out.println("回收对象" + this);
       }
    }

而后做两个测试,第一个测试没有有限循环,第二个测试放弃有限循环,循环通过一个 volatile 变量 flag 来管制:

public static void main(String[] args) throws InterruptedException {System.out.println("开始测试 1");
        resetFlag();
        flag = true;
        testLocalVariable();

        System.out.println("期待 Test1 完结");
        Thread.sleep(10000);

        System.out.println("开始测试 2");
        flag = true;
        testLocalVariable();}

看一下 testLocalVariable 办法的定义:

    public static void testLocalVariable() {Test test1 = new Test();
        Test test2 = new Test();
        while (flag) {// 啥都不做}
        test1.test();}

而后咱们再启动一个线程做定时的 GC。好了所有就绪,咱们运行吧:

 开始测试 1
创建对象 com.flydean.LocalVariableReachability$Test@119d7047
创建对象 com.flydean.LocalVariableReachability$Test@776ec8df
回收对象 com.flydean.LocalVariableReachability$Test@776ec8df
测试对象 com.flydean.LocalVariableReachability$Test@119d7047
期待 Test1 完结
回收对象 com.flydean.LocalVariableReachability$Test@119d7047

开始测试 2
创建对象 com.flydean.LocalVariableReachability$Test@4eec7777
创建对象 com.flydean.LocalVariableReachability$Test@3b07d329
回收对象 com.flydean.LocalVariableReachability$Test@3b07d329

先看测试 1 的后果,咱们能够看到第二个对象在调用 test1.test() 之前就被回收了。

再看测试 2 的后果,咱们能够看到第二个对象同样被回收了。

后果阐明了 JVM 是足够智能的,能够自行优化本地变量的生命周期。

优化的起因

咱们考虑一下,JVM 是在什么阶段对本地变量的生命周期进行优化的呢?

很显著,这个优化不是在编译期间进行的,而是在运行期中进行的优化。

咱们应用 -XX:+PrintAssembly 剖析一下汇编代码:

首先阐明,自己的汇编语言还是很多年前学过的,如果解释起来有谬误的中央,请多多斧正。

先说两个概念 rbx 和 r10 都是 64 位 CPU 的寄存器,r10d 是 r10 的低 32 位。

先看红框 1,红框 1 示意 rbx 中保留的是咱们定义的 LocalVariableReachability 类中的一个 Test 对象。

再看红框 2,红框 2 示意 r10 当初保留的是 LocalVariableReachability 这个类实例。

红框 3 示意的是进入 while 循环的时候,ImutableOopMap 中存储的对象,大家能够看到外面只有 r10 和 rbx,也就是说只有类实例和其中的一个 Test 实例。

红框 4 是什么呢?红框 4 示意的是一个 safe point,也就是垃圾回收的时候的平安点。在这个平安点上如果有不再被应用的对象就会被回收。

因为 ImutableOopMap 中只存有两个对象,那么剩下的一个 Test 实例就会被回收。

总结

本文介绍了本地变量的生命周期,并在汇编语言的角度对其进行了解释,如有谬误欢送斧正。

本文作者:flydean 程序那些事

本文链接:http://www.flydean.com/jvm-local-variable-reachability/

本文起源:flydean 的博客

欢送关注我的公众号: 程序那些事,更多精彩等着您!

正文完
 0