博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Java对象和类的生命周期
阅读量:4150 次
发布时间:2019-05-25

本文共 2534 字,大约阅读时间需要 8 分钟。

    在java当中一个对象被创建,再被引用指向,然后参与一系列的逻辑计算,到最后被垃圾回收掉,这个过程是怎样的,对我们开发来说也是极其重要的

对象的生命周期

       对象在JVM当中的生存周期一般都是从

      创建(created)-->应用(in use)-->不可见(invisiable)-->不可达(unreachable)-->收集(collected)-->终结 (finalized)-->对象空间重分配(de-allocated)

接下来介绍每个阶段主要的做什么的

创建阶段

    在创建阶段,系统需要完成下面的一系列操作

  • 为对象分配存储空间
  • 开始构建对象
  • 从父类到子类对static成员进行初始化
  • 父类成员变量按照顺序进行初始化,递归调用父类构造方法
  •  子类成员变量初始化,调用子类构造方法

   以上步骤执行结束,并且有引用指向这个对象,那么这个对象就进入到了下一个阶段使用阶段(In-use)

应用阶段

    关于应用阶段,系统至少需要维护一个对象的强引用,当然关于弱引用,软引用和虚引用我们后面的文章会进行介绍

不可见阶段

    当程序处于不可视阶段说明程序当中不再持有对象的任何强引用,简单来说就是,程序的执行超出了对象的作用域了

public void process () {     try {          Object obj = new Object();          obj.doSomething();      } catch (Exception e) {      e.printStackTrace();      }      while (isLoop) { // ... loops forever       // 这个区域对于obj对象来说已经是不可视的了          // 因此下面的代码在编译时会引发错误          obj.doSomething();       } }
    如果一个对象已经使用完了,在其可视区域不需要再使用到了,那么就可以把它指向null, 如上面的代码,可以在obj.doSomething()之后,将对象obj=null, 这样方便jvm及时对这个对象进行垃圾回收
不可达阶段

    这个阶段是指,在虚拟机所管理的对象引用根集合当中再也找不到直接或者间接的强引用,这些对象通常是指,所有线程栈当中的临时变量,所有已装载的类的静态变量或者对本地代码接口(JNI)的引用。这些对象都是准备被垃圾回收的对象,并不能直接对垃圾回收直接回收。

收集阶段

    当垃圾回收器发现对象处于不可达阶段,并且垃圾回收器已经做好了内存重新分配的准备,则对象进入收集阶段,如果该对象重写了finalize方法,则会去执行finalize方法

    (注:不建议重写finalize方法,会影响jvm对象分配和回收速度,原因是,在分配对象时,会在垃圾回收器上注册该对象,以便在垃圾回收时能执行finalize方法,在方法的执行时,需要消耗CPU,其次,在finalize方法当中可能持有其他的强引用持有该对象,会造成对象的复活,由收集阶段变为应用阶段,不利于后面的代码管理)

终结阶段

    当执行完finalize方法之后,对象仍然处于不可达状态,则对象进入到终结阶段,等待垃圾回收器对该对象的空间进行回收

重新分配

    垃圾回收器对该对象所占用的空间进行了回收或者重新分配,这个对象在程序当中彻底结束了,称之为对象空间重新分配阶段

Java类的生命周期

    类的生命周期包括以下几个阶段,加载--》连接--》初始化--》使用--》卸载,下面我们分别对每个阶段所做的事情进行一个分析

加载阶段

    当我们编写好的java文件编译成.class文件,jvm识别的就是.class这种字节码文件,类的生命周期其实就是从jvm加载class文件到最终消亡的过程,加载其实是将,class文件找到类的信息,将其加载到方法区当中,然后在内存当中生成一个java.lang.Class对象,作为方法区当中这个类的入口,

    关于加载时机,每个虚拟机的做法是不同的,但是有个原则就是当预期到某个类,需要被用到的时候,会在使用之前对这个类进行加载,比如在某个代码当中出现了一个类的名字,有的虚拟机选择去加载,而有的虚拟机会在真正用到的时候再去加载,hotspot采用的是后者。

连接

    连接阶段有分为三个小阶段,分别是,验证、准备、解析,连接阶段和加载阶段是交叉运行的,但是加载阶段一定是早于连接阶段开始的,连接阶段一定是晚于加载阶段结束的

    验证阶段:确定该类是否符合jvm规范,有没有属性和行为的重复,继承是否合理,总之就是保证jvm能够运行加载的类

    准备阶段:主要是为类的静态变量分配内存,并设置他们jvm的默认值,对于非静态变量,则不会分配内存,静态变量的初始值并不是程序当中设置的,而是每个类型的默认初始值,比如int,long之类的默认值是0,引用类型默认值是null,常量的值就是我们程序当中设定的值。

    解析:把常量池当中的符号引用解析为直接引用,就是将所有的类或者接口,字段名,方法名转换为内存地址

初始化

    这个阶段就是把静态变量赋值的过程,执行顺序,父类静态域,静态代码块,子类静态域,静态代码块

使用

    在类的使用阶段,又分为三小阶段,分别是对象实例化、垃圾回收、对象终结

    对象实例化:执行类当中的构造方法,如果该类有父类,jvm会执行父类的构造方法,在堆内存当中为父类开辟内存空间,并设置默认值,然后根据构造函数的代码将真正的赋予实例变量,然后引用变量获取对象的首地址,同过操作对象来调用实例变量和方法

    垃圾回收:当对象不再被使用的时候,就会被虚拟机标记上记号,在堆中等待gc回收

    对象终结:当对象被gc回收之后,对象就不存在了

卸载
    当满足以下条件的时候,类就会被卸载掉
  • 该类的所有实例都已经被回收,在java堆中不存在这个类的任何实例 
  • 加载该类的ClassLoader被回收
  • 该类对应的java.lang.Class对象没有被任何地方引用,无法通过反射访问该类           

    满足以上条件,jvm就会在方法区垃圾回收时,对类进行卸载,类的卸载就是清空方法区类的信息。

参考:

转载地址:http://xlvti.baihongyu.com/

你可能感兴趣的文章
经典shell面试题整理
查看>>
腾讯的一道面试题—不用除法求数字乘积
查看>>
素数算法
查看>>
java多线程环境单例模式实现详解
查看>>
将一个数插入到有序的数列中,插入后的数列仍然有序
查看>>
在有序的数列中查找某数,若该数在此数列中,则输出它所在的位置,否则输出no found
查看>>
万年历
查看>>
作为码农你希望面试官当场指出你错误么?有面试官这样遭到投诉!
查看>>
好多程序员都认为写ppt是很虚的技能,可事实真的是这样么?
查看>>
如果按照代码行数发薪水会怎样?码农:我能刷到公司破产!
查看>>
程序员失误造成服务停用3小时,只得到半月辞退补偿,发帖喊冤
查看>>
码农:很多人称我“技术”,感觉这是不尊重!纠正无果后果断辞职
查看>>
php程序员看过来,这老外是在吐糟你吗?看看你中了几点!
查看>>
为什么说程序员是“培训班出来的”就是鄙视呢?
查看>>
码农吐糟同事:写代码低调点不行么?空格回车键与你有仇吗?
查看>>
阿里p8程序员四年提交6000次代码的确有功,但一次错误让人唏嘘!
查看>>
一道技术问题引起的遐想,最后得出结论技术的本质是多么的朴实!
查看>>
985硕士:非科班自学编程感觉还不如培训班出来的,硕士白读了?
查看>>
你准备写代码到多少岁?程序员们是这么回答的!
查看>>
码农:和产品对一天需求,产品经理的需求是对完了,可我代码呢?
查看>>