1.对象的创建

  1) 当虚拟机遇到一条new的指令时,首先将去检查这个指令的参数是否能在常量池中定位到一个类的符号引用,并且检查这个符号引用代表的类是否已被加载,解析和初始化过.

  2) 在类加载检查通过后,接下来的虚拟机将为新生对象分配内存.

  3) 内存分配完成后,虚拟机需要将分配到的空间内存初始化为默认值.

  4) 接下来,虚拟机对对象进行有必要的设置,例如这个对象是哪个类的实例,如何才能找到这个类的元数据信息,对象的哈希码,对象的GC分代年龄等信息,这些信息存放在对象头.

  5) 以上工作结束后,从虚拟机角度看,对象已经创建,接下来是对对象的字段按照程序员的意思进行初始化.

2.对象的访问

  java程序需要通过栈上面的reference数据来操作堆上的具体对象.

  目前访问对象的方式有两种,一种使用句柄另一种使用直接指针:

  1) 使用句柄的话,在java堆中会划分出一块内存作为句柄池,reference中存储的就是对象的句柄地址,句柄中包含了对象的实例数据与类型数据格子的具体地址信息,这里的reference可以类比成c语言的二重指针.

  2) 使用直接指针的话,那么java堆对象的内存布局就必须考虑如何放置访问类型数据的相关信息,reference存放的就是对象的直接地址,可以类比c语言的一重指针..

  两种方法各有优劣,由于对象在堆中被移动是非常普遍的现象,前者可以只修改句柄中实例数据指针的信息,不需要修改reference的值但是它需要进行两次指针定位.后者只需要一次指针定位,速度快但是对象移动时需要修改reference的值.

3.对象的死亡

  在java中不需要程序员来管理内存,那么,我们程序中使用的实例对象在分配了空间之后何时死亡,何时回收他的内存呢?

  这里有一个很经典的算法叫做引用计数法.该算法是给对象添加一个引用计数器,每当一个地方引用便对它加一,当一个引用失效便对它减一.当计数器为0时便回收它.这个算法实现简单,判断效率高,大多数情况下是一个不错的算法,但是会这个算法无法解决两个对象相互引用的情况,比如对象A和对象B,A和B中有对方的引用,那么当其他地方的引用全部都失效之后,只剩下这两个对象的相互引用,这种情况对象AB是不会被回收的,有内存泄露的风险.

  另一个算法是可达性分析算法:这个算法是通过一系列成为"GC Roots"的对象为起点,从这些节点向下搜索,经过的路径叫做引用链,当一个对象到GC Roots没有任何引用链存在,则该对象是不可用的,应该回收.

  在java中,GC Roots对象包括:虚拟机栈(栈帧中的本地变量表)中的引用对象,方法区中类静态属性引用的对象,方法区中常量引用的对象,本地方法栈中JNI(即Native方法)引用的对象.

4.再谈引用

  从上面看到,对象是否死亡都与引用有关.JDK 1.2之后,java对引用进行了扩充:

  1) 强引用:程序代码中普遍存在的,例如"Object obj=new Object()"这类的引用,只要强引用还在,对象就不会被回收

  2) 软引用:用来描述一些非必须的但还有用的对象,软引用关联的对象,在系统将要发生内存溢出异常之前,将会把这些对象列进对象回收范围之中进行第二次回收,软引用类SoftReference.

  3) 弱引用:用来描述费必须的对象.被弱引用关联的对象会在下一次垃圾收集被回收.弱引用类WeakReference.

  4) 虚引用:虚引用完全不会对对象的生存时间构成影响,也无法通过虚引用获取对象实例.为对象设置虚引用的目的只是为了在这个对象被回收时收到一个通知.虚引用类PhantomReference.

5.生存还是死亡

  即使在可发性分析算法中不可达的对象,也不一定是死刑而是死缓.要宣告一个对象死亡,要经过至少两次标记过程:如果对象经过可达性分析后发现没有与GC Roots相连的引用链,那它会被第一次标记,并且进行一次筛选,筛选条件是此对象是否有必要执行finalzie()方法.当对象米有覆盖finalize()方法或者finalize()方法已经被虚拟机调用过,虚拟机都会视为没有必要执行.

  如果一个对象有必要执行finalize()方法,则会把这个对象放到一个F-Queue队列之中,并在稍后由虚拟机自动建立一个低优先级的Finalizer线程去执行它.这个执行是指虚拟机会触发那个方法,但是不保证会等他运行结束后.例如当主线程已经结束,Finalizer线程还未执行完,那么Finalizer将结束,不会继续执行.当Finalizer线程执行完之后,胡对F-Queue队列中的对象进行第二次标记,如果对象在finalize()方法中拯救了自己,重新与引用链上的任何一个对象建立关联(例如将自己赋给一个静态变量),第二次标记就会把它移除即将回收的集合.如果第二次依然被标记为回收,那么对象就真的会被回收.

  finalize()方法并不是C/C++中的析构函数,他运行代价高,不确定性大,无法保证各个对象的调用顺序.尽量不要使用finalize()方法.

理解JVM之对象的生命周期的更多相关文章

  1. [原创]java WEB学习笔记47:Servlet 监听器简介, ServletContext(Application 对象), HttpSession (Session 对象), HttpServletRequest (request 对象) 监听器,利用listener理解 三个对象的生命周期

    本博客为原创:综合 尚硅谷(http://www.atguigu.com)的系统教程(深表感谢)和 网络上的现有资源(博客,文档,图书等),资源的出处我会标明 本博客的目的:①总结自己的学习过程,相当 ...

  2. 第四章 Spring.Net 如何管理您的类___对象的生命周期链

    各位,实在不好意思,因为有事,博客几天没更新了.前面有童鞋提到,配置 Objects.xml 路径的相关问题,这些东西是 IResource 接口的一些内容.在下一章会详细介绍. 传统的Net应用中, ...

  3. 管中窥豹——从对象的生命周期梳理JVM内存结构、GC调优、类加载、AOP编程及性能监控

    如题,本文的宗旨既是透过对象的生命周期,来梳理JVM内存结构及GC相关知识,并辅以AOP及双亲委派机制原理,学习不仅仅是海绵式的吸收学习,还需要自己去分析why,加深对技术的理解和认知,祝大家早日走上 ...

  4. JVM类加载机制与对象的生命周期

    转载请注明原文地址:http://www.cnblogs.com/ygj0930/p/6536048.html  虚拟机把描述类的数据从Class文件加载到内存,并对数据进行校验.转换解析和初始化,最 ...

  5. JVM的内存管理、对象的生命周期、内存泄漏

    1 JVM内存 分为“堆”.“栈”和“方法区”三个区域,分别用于存储不同的数据 1.1 堆 JVM在其内存空间开辟一个称为”堆”的存储空间,这部分空间用于存储使用new关键字所创建的对象. 1.2 栈 ...

  6. 《深入理解Java虚拟机》 Java对象的生命周期

    Java虚拟机运行时数据区 方法区:存储 类信息.常量.静态变量.即使编译器编译后的代码等数据,也有别名叫做非堆.  方法区其中有包含有 运行时常量池,用于存放编译期生成的各种字面量和符号引用.其中, ...

  7. Java虚拟机(三)垃圾标记算法与Java对象的生命周期

    前言 这一节我们来简单的介绍垃圾收集器,并学习垃圾标记的算法:引用计数算法和根搜索算法,为了更好的理解根搜索算法,会在文章的最后介绍Java对象在虚拟机中的生命周期. 1.垃圾收集器概述 垃圾收集器( ...

  8. hibernate 持久化对象的生命周期 2.1

    持久化对象的生命周期 瞬态(自由态) 表示对象在内存中存在,在数据库中没有数据相关,比如刚刚new出来的一个对象 持久态 持久态指的是持久化对象处于由Hibernate管理的状态,这种状态下持久化对象 ...

  9. Java 对象的生命周期

    Java对象的生命周期 在Java中,对象的生命周期包含下面几个阶段: 1.      创建阶段(Created) 2.      应用阶段(In Use) 3.      不可见阶段(Invisib ...

随机推荐

  1. 阶段5 3.微服务项目【学成在线】_day16 Spring Security Oauth2_09-SpringSecurityOauth2研究-Oauth2密码模式授权

    密码模式(Resource Owner Password Credentials)与授权码模式的区别是申请令牌不再使用授权码,而是直接 通过用户名和密码即可申请令牌. 测试如下: Post请求:htt ...

  2. 怎样修复社区项目Karbor的Bug?

    1.准备工作. 点击Settings按钮进行设置,跳转到 https://review.openstack.org/#/settings/ 2.选择用户名称. 这个选择之后不能修改. 3.设置http ...

  3. HmacSHA256算法(C# 和 Java)

    Java代码: /** * HmacSHA256算法,返回的结果始终是32位 * @param key 加密的键,可以是任何数据 * @param content 待加密的内容 * @return 加 ...

  4. HTTP连接详解

  5. AFNetWorking实现参数以body传输请求数据

    /** * 异步POST请求:以body方式,支持数组 * * @param url 请求的url * @param body body数据 * @param success 成功回调 * @para ...

  6. .NET C#获取当前网页地址信息

    设当前页完整地址是:http://www.qiandabao.com/aaa/bbb.aspx?id=5&name=kelli "http://"是协议名"www ...

  7. pytest文档20-pytest-html报告优化(添加Description)

    前言 pytest-html测试报告默认是不展示用例描述Description内容,之前用unittest生成的报告是可以展示用例的描述,也就是test开头的用例下三个引号里面的注释(docstrin ...

  8. Docker storage driver(十四)

    目录 一.storage driver 作用 1.Images and layers 2.Container and layers Copy-on-Write 3.Data volumes and t ...

  9. Java check是否是日期类型

    boolean checkFormate(string parm){ Pattern pattern = Pattern.compile("([0-9]{4})(0[1-9]|1[0-2]) ...

  10. 笔试2019-GRANDSTREAM

    程序阅读 随机,因为局部变量在栈中,值随机. 上面那个题在x86上都是12因为x86是大端模式 但是在ARM架构的处理器,因为它们是小端模式,则输出x078 判断回文 int hui(const ch ...