内容简介:目录java方法中定义的变量,它的生命周期是什么样的呢?是不是一定要等到方法结束,这个创建的对象才会被回收呢?带着这个问题我们来看一下今天的这篇文章。
目录
简介
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的博客
欢迎关注我的公众号:程序那些事,更多精彩等着您!
以上所述就是小编给大家介绍的《JVM详解之:汇编角度理解本地变量的生命周期》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:- iOS汇编入门教程(一)ARM64汇编基础
- iOS 汇编入门教程(一):ARM64 汇编基础
- iOS汇编入门教程(三)汇编中的 Section 与数据存取
- iOS汇编入门教程(二)在Xcode工程中嵌入汇编代码
- 汇编语言8086笔记
- python编程(反汇编)
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
产品经理全栈运营实战笔记
林俊宇 / 化学工业出版社 / 49.8元
本书凝结作者多年的产品运营经验,读者会看到很多创业公司做运营的经验,书中列举了几十个互联网产品的运营案例去解析如何真正做好一个产品的冷启动到发展期再到平稳期。本书主要分为六篇:互联网运营的全面貌;我的运营生涯;后产品时代的运营之道;揭秘刷屏事件的背后运营;技能学习;深度思考。本书有很多关于产品运营的基础知识,会帮助你做好、做透。而且将理论和作者自己的案例以及其他人的运营案例结合起来,会让读者更容易......一起来看看 《产品经理全栈运营实战笔记》 这本书的介绍吧!