class A{
    List<B> list
}
class B{
     A a
}
A a = new A();
a.list = new ArrayList<>();
B b = new B();
a.list.add(b);
b.a=a;
a , b 能释放?(不要关注语法. 问了很多人 培训班的老师说除了少分号没问题,其它人说不用就释放... 按我的理解 有点醉了...所以来到这里请教) 

解决方案 »

  1.   

    a和b虽然是循环引用,但是在JAVA中JVM判断某对象是否需要清除使用的算法基本上是基于标记-清除算法的,也就是在运行过程中会对 从Roots对象开始,将所有可达的对象做标记。清除则是将遍历堆中所有的对象,没有标记的对象全部清除掉。这样即使是循环引用也没问题,可以自动被释放。所以不用关心内存释放的问题。
    注:root是指没有被其他对象引用的对象(静态属性对象、方法区常量对象等等)。具体可以看jvm垃圾回收机制原理。
      

  2.   

    会回收。测试环境: jdk 1.6.0_22 32Bit Linux ; Java HotSpot Server VM (17.1-b03, mixed-mode)
    测试代码:
    import java.util.LinkedList;
    import java.util.List;
    public class T2 { public static void main(String[] args) {
    new T2().test();
    }

    private Object lock = new Object();
    void test(){

    Thread thread = new Thread(){

    @Override
    public void run() {
    while(true){
    dowork1();

    synchronized (lock) {
    try {
    lock.wait(3000);
    } catch (InterruptedException e) {
    e.printStackTrace();
    }
    }
    }
    }
    };
    thread.setName("Thread-Test");
    thread.start();
    }

    void dowork1(){

    AA a = new AA();
    BB b = new BB();

    a.b = b;
    b.a = a; System.out.println("--1");
    } void dowork2(){ AA a = new AA();
    BB b = new BB();

    System.out.println("--2");
    }


    }class AA{
    public static final int _1MB = 1024 * 1024 ; 
    BB b;
    // char[] data = new char[10 * _1MB];
    LinkedList<Object>[] data = new LinkedList[1024];
    }class BB{
    public static final int _1MB = 1024 * 1024 ; 
    AA a;
    // char[] data = new char[10 * _1MB];
    LinkedList<Object>[] data = new LinkedList[1024];
    }当使用char[] data = new char[10 * _1MB];时,通过Java VisualVM,监测内存变更情况如下图
    当使用LinkedList<Object>[] data = new LinkedList[1024];时, 监测内存变更情况如下图所示。
    至于为啥选择LinkedList<Object>[] ,因为在默认的程序中,JVM中的LinkedList<Object>[] 对象数一般为0,而char[]这些对象的数量非常大,JDK本身也在数的new char[]和回收 char[],不便于监测。