解读JVM对象生命周期的几个阶段

开发 后端
在JVM运行空间中,整个JVM对象生命周期大致可以分为7个阶段,上节我们介绍了第一个阶段即创建阶段,这里继续向大家介绍其他几个阶段,希望对你的学习有所帮助。

在JVM运行空间中,整个JVM对象生命周期大致可以分为7个阶段:创建阶段(Creation)、应用阶段(Using)、不可视阶段(Invisible)、不可到达阶段(Unreachable)、可收集阶段(Collected)、终结阶段(Finalized)与释放阶段(Free),这里向大家描述一下除创建阶段之外的其他几个阶段。

应用阶段

这里看一个JVM对象生命周期的第二各阶段,当对象的创建阶段结束之后,该对象通常就会进入对象的应用阶段。这个阶段是对象得以表现自身能力的阶段。也就是说对象的应用阶段是对象整个生命周期中证明自身“存在价值”的时期。在对象的应用阶段,对象具备下列特征:

◆系统至少维护着对象的一个强引用(StrongReference);

◆所有对该对象的引用全部是强引用(除非我们显式地使用了:软引用(SoftReference)、弱引用(WeakReference)或虚引用(PhantomReference))。

上面提到了几种不同的引用类型。可能一些读者对这几种引用的概念还不是很清楚,下面分别对之加以介绍。在讲解这几种不同类型的引用之前,我们必须先了解一下Java中对象引用的结构层次。

Java对象生命周期引用的结构层次示意如图2-6所示。

对象引用的结构层次示意

由图2-6我们不难看出,上面所提到的几种JVM对象生命周期引用的层次关系,其中强引用处于顶端,而虚引用则处于底端。下面分别予以介绍。

1.强引用

强引用(StrongReference)是指JVM内存管理器从根引用集合(RootSet)出发遍寻堆中所有到达对象的路径。当到达某对象的任意路径都不含有引用对象时,对这个对象的引用就被称为强引用。

2.软引用

软引用(SoftReference)的主要特点是具有较强的引用功能。只有当内存不够的时候,才回收这类内存,因此在内存足够的时候,它们通常不被回收。另外,这些引用对象还能保证在Java抛出OutOfMemory异常之前,被设置为null。它可以用于实现一些常用资源的缓存,实现Cache的功能,保证***限度的使用内存而不引起OutOfMemory。再者,软可到达对象的所有软引用都要保证在虚拟机抛出OutOfMemoryError之前已经被清除。否则,清除软引用的时间或者清除不同对象的一组此类引用的顺序将不受任何约束。然而,虚拟机实现不鼓励清除最近访问或使用过的软引用。下面是软引用的实现代码:

  1. ……  
  2. importjava.lang.ref.SoftReference;  
  3. …  
  4. Aa=newA();  
  5. …  
  6. //使用a  
  7. …  
  8. //使用完了a,将它设置为soft引用类型,并且释放强引用;  
  9. SoftReferencesr=newSoftReference(a);  
  10. a=null;  
  11. …  
  12. //下次使用时  
  13. if(sr!=null){  
  14. a=sr.get();  
  15. }  
  16. else{  
  17. //GC由于内存资源不足,可能系统已回收了a的软引用,  
  18. //因此需要重新装载。  
  19. a=newA();  
  20. sr=newSoftReference(a);  
  21. }  
  22. ……  
  23.  

 软引用技术的引进,使Java应用可以更好地管理内存,稳定系统,防止系统内存溢出,避免系统崩溃(crash)。因此在处理一些占用内存较大而且声明周期较长,但使用并不频繁的对象时应尽量应用该技术。正像上面的代码一样,我们可以在对象被回收之后重新创建(这里是指那些没有保留运行过程中状态的对象),提高应用对内存的使用效率,提高系统稳定性。

但事物总是带有两面性的,有利亦有弊。在某些时候对软引用的使用会降低应用的运行效率与性能,例如:应用软引用的对象的初始化过程较为耗时,或者对象的状态在程序的运行过程中发生了变化,都会给重新创建对象与初始化对象带来不同程度的麻烦,有些时候我们要权衡利弊择时应用。

3.弱引用

弱引用(WeakReference)对象与Soft引用对象的***不同就在于:GC在进行回收时,需要通过算法检查是否回收Soft引用对象,而对于Weak引用对象,GC总是进行回收。因此Weak引用对象会更容易、更快被GC回收。虽然,GC在运行时一定回收Weak引用对象,但是复杂关系的Weak对象群常常需要好几次GC的运行才能完成。Weak引用对象常常用于Map数据结构中,引用占用内存空间较大的对象,一旦该对象的强引用为null时,对这个对象引用就不存在了,GC能够快速地回收该对象空间。与软引用类似我们也可以给出相应的应用代码: 

  1. ……  
  2. importjava.lang.ref.WeakReference;  
  3. …  
  4. Aa=newA();  
  5. …  
  6. //使用a  
  7. …  
  8. //使用完了a,将它设置为weak引用类型,并且释放强引用;  
  9. WeakReferencewr=newWeakReference(a);  
  10. a=null;  
  11. …  
  12. //下次使用时  
  13. if(wr!=null){  
  14. a=wr.get();  
  15. }  
  16. else{  
  17. a=newA();  
  18. wr=newWeakReference(a);  
  19. }  
  20. ……  

 弱引用技术主要适用于实现无法防止其键(或值)被回收的规范化映射。另外,弱引用分为“短弱引用(ShortWeekReference)”和“长弱引用(LongWeekReference)”,其区别是长弱引用在对象的Finalize方法被GC调用后依然追踪对象。基于安全考虑,不推荐使用长弱引用。因此建议使用下面的方式创建对象的弱引用。 

  1. ……  
  2. WeakReferencewr=newWeakReference(obj);  
  3. 或  
  4. WeakReferencewr=newWeakReference(obj,false);  
  5. ……  

 4.虚引用

虚引用(PhantomReference)的用途较少,主要用于辅助finalize函数的使用。Phantom对象指一些执行完了finalize函数,并且为不可达对象,但是还没有被GC回收的对象。这种对象可以辅助finalize进行一些后期的回收工作,我们通过覆盖Reference的clear()方法,增强资源回收机制的灵活性。虚引用主要适用于以某种比java终结机制更灵活的方式调度pre-mortem清除操作。
&注意在实际程序设计中一般很少使用弱引用与虚引用,使用软引用的情况较多,这是因为软引用可以加速JVM对垃圾内存的回收速度,可以维护系统的运行安全,防止内存溢出(OutOfMemory)等问题的产生。#p#

不可视阶段

在一个对象经历了应用阶段之后,那么该对象便处于JVM对象生命周期的不可视阶段,说明我们在其他区域的代码中已经不可以再引用它,其强引用已经消失,例如,本地变量超出了其可视范围,如下所示。 

  1. ……  
  2. publicvoidprocess(){  
  3. try{  
  4. Objectobj=newObject();  
  5. obj.doSomething();  
  6. }catch(Exceptione){  
  7. e.printStackTrace();  
  8. }  
  9. while(isLoop){//...loopsforever  
  10. //这个区域对于obj对象来说已经是不可视的了  
  11. //因此下面的代码在编译时会引发错误  
  12. obj.doSomething();  
  13. }  
  14. }  
  15. ……  

 如果一个对象已使用完,而且在其可视区域不再使用,此时应该主动将其设置为空(null)。可以在上面的代码行obj.doSomething();下添加代码行obj=null;,这样一行代码强制将obj对象置为空值。这样做的意义是,可以帮助JVM及时地发现这个垃圾对象,并且可以及时地回收该对象所占用的系统资源。

不可到达阶段

处于JVM对象生命周期不可到达阶段的对象,在虚拟机所管理的对象引用根集合中再也找不到直接或间接的强引用,这些对象通常是指所有线程栈中的临时变量,所有已装载的类的静态变量或者对本地代码接口(JNI)的引用。这些对象都是要被垃圾回收器回收的预备对象,但此时该对象并不能被垃圾回收器直接回收。其实所有垃圾回收算法所面临的问题是相同的——找出由分配器分配的,但是用户程序不可到达的内存块。

可收集阶段、终结阶段与释放阶段

JVM对象生命周期的***一个阶段是可收集阶段、终结阶段与释放阶段。当对象处于这个阶段的时候,可能处于下面三种情况:

(1)垃圾回收器发现该对象已经不可到达。

(2)finalize方法已经被执行。

(3)对象空间已被重用。

当对象处于上面的三种情况时,该对象就处于可收集阶段、终结阶段与释放阶段了。虚拟机就可以直接将该对象回收了。
 

【编辑推荐】

  1. 解读JVM对象生命周期之创建阶段
  2. Tomcat配置JVM参数巧妙方法
  3. JVM基础:解析JVM分代垃圾回收策略
  4. JVM for Linux JIT诊断技术简介
  5. 巧解IBM JVM for Linux onPOWER性能调优

 

 

责任编辑:佚名 来源: javaeye.com
相关推荐

2010-09-27 10:30:42

JVM对象生命周期

2009-03-04 10:18:50

生命周期JVMjava

2013-08-19 17:03:00

.Net生命周期对象

2010-01-15 13:52:44

VB.NET对象生命周

2009-06-17 15:06:50

Hibernate实体

2015-07-08 16:28:23

weak生命周期

2022-04-19 07:20:24

软件开发安全生命周期SSDLC应用安全

2010-07-14 10:48:37

Perl线程

2009-06-11 11:28:35

JSF生命周期

2011-07-07 14:22:27

Cocoa 对象 生命周期

2022-08-02 08:00:00

机器学习数据框架

2009-07-23 18:55:17

ASP.NET页生命周

2019-10-16 10:50:13

Linux内核测试

2012-01-16 09:00:56

线程

2013-07-29 05:11:38

iOS开发iOS开发学习类的'生命周期'

2012-04-28 13:23:12

Java生命周期

2011-06-16 09:31:21

ActivityAndroid

2009-06-18 13:32:39

Java线程生命周期

2012-06-20 10:29:16

敏捷开发

2009-06-24 10:47:55

JSF生命周期
点赞
收藏

51CTO技术栈公众号