现在的位置: 首页 > 综合 > 正文

jvm如何判断对象已死?

2018年07月12日 ⁄ 综合 ⁄ 共 1781字 ⁄ 字号 评论关闭


在java的垃圾回收中,jvm是如何判断堆中的对象是否已死呢?主流的判断方法有两种。 

1.引用计数算法: 
  这种算法的思路是如果某一个对象被别的对象引用,那么就把他们引用计数器加上1,这样当进行垃圾回收时如何判断该引用的数量为0,此时就代表没有进行任何对象对其进行引用,这种方法判断效率很高,在很多情况下是个不错的选择,例如微软的COM,AS3的FlashPlayer,Python语言等都是采用引用计数器进行判断的,java没有采用此
用法的原因是他无法解决循环引用的问题。 

eg : 
public class RefernceCountGC{ 
   public static instance = null; 
   public static final int _1MB = 1024 * 1024 ; 
  
   private byte[] bigSize = new byte[2 * _1MB]; 
   public static void testGC(){ 
      RefernceCountGC  objA = new RefernceCountGC(); 
      RefernceCountGC  objB = new RefernceCountGC(); 
     
     objA.instance= objB ; 
     objB.instance = objA ; 
     objA = null; 
     objB = null ; 
     System.gc(); 
  } 

上面的两个对象objA和objB相互引用,如果用计算器算法的话会导致无法进行回收。 

2.根搜索算法: 
   主流的语言Java,C#甚至古老的语言Lisp都是采用根搜索算法进行垃圾回收的,这个算法的思路就是通过命名一系列的“GC Root"作为起点,从这些起点开始向下搜索,这样可以形成一条引用链,该引用链之外的对象都将被回收,在java钟只有一下的对象才可以被作为GC Root. 
1>虚拟机栈(栈帧中的本地方法表)中引用的对象。 
2>方法区中类静态属性引用的对象。 
3>方法区中常量引用的对象。 
4>本地方法栈JNI(即一般说的Native方法)的引用对象。 
3.关于引用: 
  在jdk1.2之前,java中的引用时这样定义的:如果reference类型的数据中存储的是另一块内存的起始地址,就称这块内存代表着一个引用。这样定义过于狭隘,因为这是一个对象只有引用和被引用两种状态,描述一下"食之无味,弃之可惜"的对象则无能无力,我们希望描述这样的一类对象,当内存空间还够是,则能留在内存中,否则内存进行垃圾回收后还紧张,那么可以抛弃这些对象,jdk1.2后对引用进行了扩充,分为:强引用(Strong
Reference),软引用(Soft Reference),弱引用(Weak Reference),虚引用(Phantom Reference)四种。 

  3.1 强引用。 
   该引用是代码中普通存在的,例如Object objA = new Object(),只要强引用存在,垃圾收集器永远不会回收掉被引用的对象。 
  3.2 软引用。 
  该引用用来描述一些还有用,但是并非必须得对象,在系统将要爆发内存溢出之前,将会把这些对象列在进行回收的范围之内,进行二次回收后如果还是内存不足,这时候才跑出内存溢出的错误。 
  3.3 若引用。 
   该引用也是用来描述非必须对象的,强度比软引用更弱被若引用引用的对象只能存活到下一次垃圾回收之前。 
  3.4 虚引用也称为幻影引用。 
  是最弱的一种的引用,一个对象是否存活与其生存周期没有什么影响,设置该引用的目的仅仅 是希望这个对象被释放的时候能够收到一个系统通知。 

4.生存还是死亡? 
  如果进行垃圾回收的时候发现一个对象没有在GC Root链上,那么就需要进行两次的标记过程,如果当前发现没有关联在GC Root链上,那么就会进行第一次标记,如果此时对象的finalize()方法没有被覆盖或该方法已经被虚拟机调用过,那么此时将被标记为没有必要执行,此时该对象会被放入”即将回收“集合,否则就会放入F-Queue的对象中等待执行finalize()方法,如果在此方法中对象将自己与GC
Root链上的任何一个对象关联,那么就会被溢出”即将回收“集合。


转自:http://boyseegirl.iteye.com/blog/1684169




抱歉!评论已关闭.