JVM 详解之: 汇编角度理解本地变量的生命周期
简介
java 方法中定义的变量,它的生命周期是什么样的呢?是不是一定要等到方法结束,这个创建的对象才会被回收呢?
带着这个问题我们来看一下今天的这篇文章。
本地变量的生命周期
在类中,变量类型有类变量,成员变量和本地变量。
本地变量指的是定义在方法中的变量,如果我们在方法中定义了一个变量,那么这个变量的生命周期是怎么样的呢?
举个例子:
在上面的 test 方法中,定义了一个 object 本地变量,然后又执行了一个方法。
因为在 java 中,我们无法直接控制对象的生命周期,对象的回收是由垃圾回收器自动进行的。
通常来说这个 object 对象会维持到整个 test 执行结束才会被回收。
现在我们考虑一个特殊的情况,如果 doSomeThingElse 这个方法是一个 while 循环,并且永远不会结束,那么这个创建出来的 object 对象会不会被回收呢?还是一直都存在内存中?
先说我们的结论,JVM 非常智能,可以检测出来这种情况,将 object 对象进行回收。
举例说明
为了能够更好的说明问题,我们自定义一个 Test 对象,并在其创建和被回收之前打印相应的信息。
然后做两个测试,第一个测试没有无限循环,第二个测试保持无限循环,循环通过一个 volatile 变量 flag 来控制:
看一下 testLocalVariable 方法的定义:
然后我们再启动一个线程做定时的 GC。好了一切就绪,我们运行吧:
先看测试 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 的博客
欢迎关注我的公众号:程序那些事,更多精彩等着您!
版权声明: 本文为 InfoQ 作者【程序那些事】的原创文章。
原文链接:【http://xie.infoq.cn/article/5d0ae1221db7442f95fc08272】。文章转载请联系作者。
评论