简介

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详解之:汇编角度理解本地变量的生命周期的更多相关文章

  1. ARP协议详解之ARP动态与静态条目的生命周期

    ARP协议详解之ARP动态与静态条目的生命周期 ARP动态条目的生命周期 动态条目随时间推移自动添加和删除. q  每个动态ARP缓存条目默认的生命周期是两分钟.当超过两分钟,该条目会被删掉.所以,生 ...

  2. JVM详解总结

    JVM详解总结 1.JVM内存模型 1.1 运行时数据区内存分布实例 1.2 类加载的生命周期 2.物理内存与虚拟内存 3.Java中需要使用内存的组件 3.1 Java堆 3.2 线程 3.3 类和 ...

  3. Mysql加锁过程详解(8)-理解innodb的锁(record,gap,Next-Key lock)

    Mysql加锁过程详解(1)-基本知识 Mysql加锁过程详解(2)-关于mysql 幻读理解 Mysql加锁过程详解(3)-关于mysql 幻读理解 Mysql加锁过程详解(4)-select fo ...

  4. JNI详解---从不懂到理解

    转载:https://blog.csdn.net/hui12581/article/details/44832651 Chap1:JNI完全手册... 3 Chap2:JNI-百度百科... 11 C ...

  5. JVM 详解

    概念 数据类型 Java 虚拟机中,数据类型可以分为两类:基本类型和引用类型.基本类型的变量保存原始值,即:他代表的值就是数值本身:而引用类型的变量保存引用值.“引用值”代表了某个对象的引用,而不是对 ...

  6. jdk与jre与jdk都是干什么的有什么区别和jvm详解:

    1.0,jdk与jre和jvm的区别: JDK(Java Development Kit):指的是Java开发工具集.JDK是整个Java的核心,包括了Java基础类库.Java运行环境(JRE)和J ...

  7. WmS详解(二)之如何理解Window和窗口的关系?基于Android7.0源码

    上篇博客(WmS详解(一)之token到底是什么?基于Android7.0源码)中我们简要介绍了token的作用,这里涉及到的概念非常多,其中出现频率最高的要数Window和窗口这一对搭档了,那么我们 ...

  8. 百度大脑UNIT3.0详解之嵌入式对话理解技术

    相信很多人都体验过手机没有网时的焦虑,没有网什么也做不了.而机器人也会遇到这样的时刻,没有网或者网络环境不好的情况下,无法识别用户在说什么,也无法回复用户.在AIoT(AI+物联网)飞速普及的现在,智 ...

  9. OPCode详解及汇编与反汇编原理

    1. 何为OPCode 在计算机科学领域中,操作码(Operation Code, OPCode)被用于描述机器语言指令中,指定要执行某种操作的那部分机器码,构成OPCode的指令格式和规范由处理器的 ...

随机推荐

  1. 《JavaScript高级程序设计》(第二版)

    这本书的作者是 Nicholas C.Zakas ,博客地址是 http://www.nczonline.net/ ,大家可以去多关注,雅虎的前端工程师,是YUI的代码贡献者,可想而知这本书得含金量, ...

  2. Spring FactoryBean 缓存

    相关文章 Spring 整体架构 编译Spring5.2.0源码 Spring-资源加载 Spring 容器的初始化 Spring-AliasRegistry Spring 获取单例流程(一) Spr ...

  3. Ribbon软负载 (F版)

    Spring Cloud 为开发者提供了在分布式系统中的一些常用的组件(例如配置管理,服务发现,断路器,智能路由,微代理,控制总线,一次性令牌,全局锁定,决策竞选,分布式会话集群状态).使用Sprin ...

  4. 理解css中Grid布局,在项目中如何实现grid页面布局

    简介 CSS中Grid是一种二维网格式布局方式.我们常规使用table.float.position.inline-block等布局,但它们遗漏了很多功能,例如垂直居中.后来css3中flexbox的 ...

  5. P4408 逃学的小孩 题解

    题目描述 Chris家的电话铃响起了,里面传出了Chris的老师焦急的声音:"喂,是Chris的家长吗?你们的孩子又没来上课,不想参加考试了吗?"一听说要考试,Chris的父母就心 ...

  6. # Mysql常用函数总结(一)

    Mysql常用函数总结(一) 博客已搬家,更多内容查看https://liangyongrui.github.io/ 遇到什么总结什么 DATE_SUB(date,INTERVAL expr type ...

  7. [JAVA]SpringBoot中让接口支持跨域

    官方原文:https://spring.io/blog/2015/06/08/cors-support-in-spring-framework ===抽空翻译 最简单办法:在方法上增加注解: @Cro ...

  8. JVM 专题九:运行时数据区(四)本地方法栈

    1. 本地方法栈 2. 什么是本地方法栈? Java虚拟机栈用于管理Java方法的调用,而本地方法栈用于管理本地方法的调用   本地方法栈,也是线程私有的. 允许被实现成固定或者是可动态拓展的内存大小 ...

  9. Show information of directory or disk

    There are so many commands of Ubuntu, we just need to know useful and high-frequency commands. I hav ...

  10. 浏览器常见攻击方式(XSS和CSRF)

    常见的浏览器攻击分为两种,一种为XSS(跨站脚本攻击),另一种则为CSRF(跨站请求伪造). XSS(跨站脚本攻击) 定义 XSS 全称是 Cross Site Scripting,为了与“CSS”区 ...