在 Java 中释放自阻塞引用
Releasing self-blocking references in Java
这是一个相当常见的情况:classTeam 包含其所有 Member 实例的列表,而 Member 指的是其 Team。 Java 代码看起来像这样:
public class Team {
private String name;
private List<Member> members;
public Team(final String name, final String... memberNames) {
this.name = name;
members = new LinkedList<>();
for (String memberName : memberNames)
members.add(new Member(memberName, this));
}
public String getName() {
return name;
}
@Override
public String toString() {
return name + ": " + members;
}
}
class Member {
private String name;
private Team team;
public Member(final String name, Team team) {
this.name = name;
this.team = team;
}
@Override
public String toString() {
return name + " of " + team.getName();
}
}
再考虑一个函数 test
,它创建一个 Team
实例并终止。
public static void test() {
Team team = new Team("Family",
"William", "Kate", "George");
System.out.print(team);
}
根据常识,函数测试结束后,team
对象及其所有Member
实例应该被释放。但是 team
的引用计数是非零的,因为所有 Member
-s 都引用它,而每个 Member
不能被释放,因为 team
持有它。
一些语言提供所谓的"weak references"(不增加引用计数,但在释放引用对象时自动设置为空)来解决这个问题,但是Java没有类似的东西那。
我可以想象一个 GC 引擎识别出 "closed" 一组相互引用但没有外部引用的对象,这样的一组对象可以被释放。但是 JVM 就一定那么聪明吗?我还没有找到任何 Java 文件来讨论这个问题,所以每次我必须创建这种结构时我都很担心。我对 Dalvik VM 特别感兴趣。
Java中的垃圾收集不是通过计算引用来工作,而是从可直接访问的对象开始:在堆栈上,在静态字段中,以及永久可访问的对象,例如类;然后它找到这些对象引用的每个对象,依此类推,并将所有引用链无法访问的对象标记为垃圾。因此,它总是会释放循环引用的垃圾,而不需要使用 WeakReference
.
这是一个相当常见的情况:classTeam 包含其所有 Member 实例的列表,而 Member 指的是其 Team。 Java 代码看起来像这样:
public class Team {
private String name;
private List<Member> members;
public Team(final String name, final String... memberNames) {
this.name = name;
members = new LinkedList<>();
for (String memberName : memberNames)
members.add(new Member(memberName, this));
}
public String getName() {
return name;
}
@Override
public String toString() {
return name + ": " + members;
}
}
class Member {
private String name;
private Team team;
public Member(final String name, Team team) {
this.name = name;
this.team = team;
}
@Override
public String toString() {
return name + " of " + team.getName();
}
}
再考虑一个函数 test
,它创建一个 Team
实例并终止。
public static void test() {
Team team = new Team("Family",
"William", "Kate", "George");
System.out.print(team);
}
根据常识,函数测试结束后,team
对象及其所有Member
实例应该被释放。但是 team
的引用计数是非零的,因为所有 Member
-s 都引用它,而每个 Member
不能被释放,因为 team
持有它。
一些语言提供所谓的"weak references"(不增加引用计数,但在释放引用对象时自动设置为空)来解决这个问题,但是Java没有类似的东西那。
我可以想象一个 GC 引擎识别出 "closed" 一组相互引用但没有外部引用的对象,这样的一组对象可以被释放。但是 JVM 就一定那么聪明吗?我还没有找到任何 Java 文件来讨论这个问题,所以每次我必须创建这种结构时我都很担心。我对 Dalvik VM 特别感兴趣。
Java中的垃圾收集不是通过计算引用来工作,而是从可直接访问的对象开始:在堆栈上,在静态字段中,以及永久可访问的对象,例如类;然后它找到这些对象引用的每个对象,依此类推,并将所有引用链无法访问的对象标记为垃圾。因此,它总是会释放循环引用的垃圾,而不需要使用 WeakReference
.