简介
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的博客
欢送关注我的公众号:程序那些事,更多精彩等着您!