深入JVM——垃圾收集器(二)

转自:http://xtu-tja-163-com.iteye.com/blog/771423

上篇文章主要描述了一下垃圾收集器的收集方式以及收集器的种类。如果对垃圾收集器还不是很了解的朋友可以去网上搜索下资料看看,或直接看《深入JVM》,如果觉得麻烦,可以看看我上篇blog。地址是:

 http://xtu-tja-163-com.iteye.com/blog/771401

 

   使用垃圾收集器要注意的地方

 

下面将提出一些有关垃圾收集器要注意的地方和一些面试题的分析。垃圾收集器知识很多,下面我只列出一部分我觉得有用的知识:

 

1. 每个对象只能调用finalize(   )方法一次。如果在finalize(   )方法执行时产生异常(exception),则该对象仍可以被垃圾收集器收集。

 

2. 垃圾收集器跟踪每一个对象,收集那些不可触及的对象(即该对象不再被程序引用 了),回收其占有的内存空间。但在进行垃圾收集的时候,垃圾收集器会调用该对象的finalize(   )方法(如果有)。如果在finalize()方法中,又使得该对象被程序引用(俗称复活了),则该对象就变成了可触及的对象,暂时不会被垃圾收集了。但是由于每个对象只能调用一次finalize(   )方法,所以每个对象也只可能 "复活 "一次。

 

3. Java语言允许程序员为任何方法添加finalize(   )方法,该方法会在垃圾收集器交换回收对象之前被调用。但不要过分依赖该方法对系统资源进行回收和再利用,因为该方法调用后的执行结果是不可预知的。

 

4. 垃圾收集器不可以被强制执行,但程序员可以通过调研System.gc方法来建议执行垃圾收集。记住,只是建议。一般不建议自己写System.gc,因为会加大垃圾收集工作量。

 

   有关垃圾收集器面试题分析

 

   下面举几个java收集的例子(都是从网上搜集来的),以便大家可以更加深刻的理解垃圾收集,具体详细信息,可以参考文章:http://www.360doc.com/content/10/0822/18/1780254_47975944.shtml

 

  在做题前,大家首先要明白:Java语言中,判断一块内存空间是否符合垃圾收集器收集标准是程序中是否还有引用指向该对象,一般出现被回收,有以下几种情况:

1.给对象对应的所有引用赋予了空值null,以下再没有调用过。
2
.给对象对应的所有引用赋予了新值,既重新分配了内存空间。

3.该对象引用有的被赋予了null,有的指向了新的对象。总之,就是以前指向该对象的所有引用现在都不指向它了。

 

     

程序段 1:
1.fobj = new Object ( ) ;
2.fobj. Method ( ) ;
3.fobj = new Object ( ) ;
4.fobj. Method ( ) ; 

 

问:这段代码中,第几行的内存空间符合垃圾收集器的收集标准?
答:第1行。因为第3行的fobj被赋了新值,产生了一个新的对象,即换了一块新的内存空间,也相当于为第1行中的fobj赋了null值。这种类型的题在认证0考试中是最简单的。

疑问:感觉第2行还用了fobj对象啊,如果在第一行被收集了,那第二行还能被执行吗? 

 

 程序段2:
1.Object sobj = new Object ( ) ;
2.Object sobj = null ;
3.Object sobj = new Object ( ) ;
4.sobj = new Object ( ) ;

 

问:这段代码中,第几行的内存空间符合垃圾收集器的收集标准?
答:第1行和第3行。因为第2行为sobj赋值为null,所以在此第1行的sobj符合垃圾收集器的收集标准。而第4行相当于为sobj赋值为null,所以在此第3行的sobj也符合垃圾收集器的收集标准。
如果有一个对象的句柄a,且你把a作为某个构造器的参数,即 new Constructor ( a )的时候,即使你给a赋值为null,a也不符合垃圾收集器的收集标准。直到由上面构造器构造的新对象被赋空值时,a才可以被垃圾收集器收集。

程序段3:  个人感觉有点问题,大家知道的可以讨论下
1.Object aobj = new Object ( ) ;
2.Object bobj = new Object ( ) ;
3.Object cobj = new Object ( ) ;
4.aobj = bobj;
5.aobj = cobj;
6.cobj = null;
7.aobj = null;

 

问:这段代码中,第几行的内存空间符合垃圾收集器的收集标准?

答:第7行。注意这类题型是认证考试中可能遇到的最难题型了。
行1-3分别创建了Object类的三个对象:aobj,bobj,cobj
行4:此时对象aobj的句柄指向bobj,所以该行的执行不能使aobj符合垃圾收集器的收集标准。
行5:此时对象aobj的句柄指向cobj,所以该行的执行不能使aobj符合垃圾收集器的收集标准。
行6:此时仍没有任何一个对象符合垃圾收集器的收集标准。
行7:对象cobj符合了垃圾收集器的收集标准,因为cobj的句柄指向单一的地址空间。在第6行的时候,cobj已经被赋值为null,但由cobj同时还指向了aobj(第5行),所以此时cobj并不符合垃圾收集器的收集标准。而在第7行,aobj所指向的地址空间也被赋予了空值null,这就说明了,由cobj所指向的地址空间已经被完全地赋予了空值。所以此时cobj最终符合了垃圾收集器的收集标准。 但对于aobj和bobj,仍然无法判断其是否符合收集标准。个人认为答案: 1和7行

 

最后再次提醒一下:一块内存空间符合了垃圾收集器的收集标准,并不意味着这块内存空间就一定会被垃圾收集器收集

 

 

 

 

最后一个比较难的题了,如果你会做,那证明你对JVM有比较深的了解了:

      

Java代码   收藏代码
  1. class Beta{}   
  2. class Alpha{ static Beta b1; Beta b2; }   
  3.   
  4. //执行代码   
  5. Beta b1 = new Beta();   
  6. Beta b2 = new Beta();   
  7. Alpha a1 = new Alpha();   
  8. Alpha a2 = new Alpha();   
  9. a1.b1 = b1;   
  10. a1.b2 = b1;   
  11. a2.b2 = b2;   
  12. a1 = null;   
  13. b1 = null;   
  14. b2 = null;   

 

 

 

 

       问:程序执行完b2=null后,理论上有几个对象被回收了?

       答案:http://zhidao.baidu.com/question/143700758.html?fr=ala0

你可能感兴趣的:(jvm)