Circular References in Java

2019-01-04 02:17发布

Given an aggregation of class instances which refer to each other in a complex, circular, fashion: is it possible that the garbage collector may not be able to free these objects?

I vaguely recall this being an issue in the JVM in the past, but I thought this was resolved years ago. yet, some investigation in jhat has revealed a circular reference being the reason for a memory leak that I am now faced with.

Note: I have always been under the impression that the JVM was capable of resolving circular references and freeing such "islands of garbage" from memory. However, I am posing this question just to see if anyone has found any exceptions.

10条回答
我欲成王,谁敢阻挡
2楼-- · 2019-01-04 02:31

A circular reference happens when one object refers to another, and that other one refers to the first object. For example:

class A {
private B b;

public void setB(B b) {
    this.b = b;
}
}

class B {
private A a;

public void setA(A a) {
    this.a = a;
}
}

public class Main {
public static void main(String[] args) {
    A one = new A();
    B two = new B();

    // Make the objects refer to each other (creates a circular reference)
    one.setB(two);
    two.setA(one);

    // Throw away the references from the main method; the two objects are
    // still referring to each other
    one = null;
    two = null;
}
}

Java's garbage collector is smart enough to clean up the objects if there are circular references, but there are no live threads that have any references to the objects anymore. So having a circular reference like this does not create a memory leak.

查看更多
男人必须洒脱
3楼-- · 2019-01-04 02:35

No, at least using Sun's official JVM, the garbage collector will be able to detect these cycles and free the memory as soon as there are no longer any references from the outside.

查看更多
Deceive 欺骗
4楼-- · 2019-01-04 02:38

The Java specification says that the garbage collector can garbage collect your object ONLY If it is not reachable from any thread.

Reachable means there is a reference, or chain of references that leads from A to B, and can go via C,D,...Z for all it cares.

The JVM not collecting things has not been a problem for me since 2000, but your mileage may vary.

Tip: Java serialization caches objects to make object mesh transfer efficient. If you have many large, transient objects, and all your memory is getting hogged, reset your serializer to clear it's cache.

查看更多
▲ chillily
5楼-- · 2019-01-04 02:43

Reference counting GCs are notorious for this issue. Notably, Suns JVM doesn't use a reference counting GC.

If the object can not be reach from the root of the heap (typically, at a minimum, through the classloaders if nothing else0, then the objects will be destroyed as they are not copied during a typical Java GC to the new heap.

查看更多
beautiful°
6楼-- · 2019-01-04 02:50

Just to amplify what has already been said:

The application I've been working on for six years recently changed from Java 1.4 to Java 1.6, and we've discovered that we've had to add static references to things that we didn't even realize were garbage collectable before. We didn't need the static reference before because the garbage collector used to suck, and it is just so much better now.

查看更多
Melony?
7楼-- · 2019-01-04 02:51

If I remember correctly, then according to the specifications, there are only guarantees about what the JVM can't collect (anything reachable), not what it will collect.

Unless you are working with real-time JVMs, most modern garbage collectors should be able to handle complex reference structures and identify "subgraphs" that can be eliminated safely. The efficiency, latency, and likelihood of doing this improve over time as more research ideas make their way into standard (rather than research) VMs.

查看更多
登录 后发表回答