日期:2014-05-20  浏览次数:20942 次

关于GC回收对象问题
class C{
publicObject x;
}
C obj1、obj2= new C();
obj1.x = obj2;
obj2.x = obj1;
obj1、obj2= null;

请问gc启动时,会回收obj1和obj2引用的对象么?
请说出理由。。

------解决方案--------------------
个人感觉应该会。
理由就是GC的机制,
回收机制就是 当一些资源被创建使用之后或不在调用的话 就会变成垃圾,垃圾的话会占用空间,这时候就需要释放空间给其他程序使用,所以JAVA拥有自动垃圾回收机制,会在适当的时候自动调用垃圾回收 释放资源,程序员也可以手动调用释放资源等等。
而很明显上面的那个对象符合这样的标准。
------解决方案--------------------
top top top
------解决方案--------------------
1、各厂商jvm实现不同,采用的垃圾回收策略也不一样,jvm垃圾回收算法主要有引用计数、标记清除、分代回收、、、、
2、就题目而言,lz希望通过实现一个循环引用来干扰jvm进行垃圾回收,但是在最后又将obj1、obj2= null,这里将两个引用设置成null,所以个人觉得jvm是可以回收的。
3、就算是内存中存在循环引用,只要是循环中的对象没有别其他对象引用,也是有可能被回收的,取决于jvm采用的垃圾回收算法(比如复制算法就能回收,但是引用计数算法可能无法回收)
------解决方案--------------------
我的理解会回收,可以在类C里重写finalize()方法,加一输出语句测试。当然,仅仅产生两个对象,虚拟机不会启动垃圾回收的,所以代码里产生大量的C对象。
当代码重复产生大量的C的对象,并把引用赋值null后,会看到大量的对象的finalize()在运行,说明这些对象都成为了垃圾,并被回收了。
而当我们把代码改一下,把这些对象都放在容器里,这时就看不到任何输出了。
个人认为,两个失去了引用的对象,尽管内部互为引用,但还是会被当成垃圾的。

import java.util.*;

public class TestGc
{
//static List<C> listC1=new ArrayList<C>(); //运行完后去掉这两行注释,(下面的两行也去掉)
//static List<C> listC2=new ArrayList<C>();//看看效果。
public static void main(String[] args)
{
C c1=null;
C c2=null;
for(int i=0;i<1000000;i++)//产生大量的对象。每次循环产生2个。
{
c1=new C();
c2=new C();
c1.x=c2;
c2.x=c1;
//listC1.add(c1);
//listC2.add(c2);
c1=null;
c2=null;
}
}
}
class C 
{
static int i=0;
public int id=0;
public Object x;
public C()
{
id=i++;
}
public void finalize()
{
System.out.println("The Object in C "+id+"is going!......");
}
}


------解决方案--------------------
应该是可以被回收的,Sun的JVM并没有采用引用计数算法来进行垃圾回收。采用的是根搜索算法,可以回收这种互相引用。
------解决方案--------------------
垃圾回收器会回收这两个对象.