Java 理论与实践: 它是谁的对象?
垃圾收集减少了跟踪对象所有权的需要——但是并没有消除这种需要
在没有垃圾收集的语言中,比如 C++,必须特别关注内存管理。对于每个动态对象,必须要么实现引用
计数以模拟 垃圾收集效果,要么管理每个对象的“所有权”――确定哪个类负责删除一个对象。通常,对这
种所有权的维护并没有什么成文的规则,而是按照约定(通常是不成文的)进行维护。尽管垃圾收集意味
着 Java 开发者不必太多地担心内存 泄漏,有时我们仍然需要担心对象所有权,以防止数据争用(data
races)和不必要的副作用。在这篇文章中,Brian Goetz 指出了一些这样的情况,即 Java 开发者必须
注意对象所有权。请在 论坛上与作者及其他读者共享您对本文的一些想法(您也可以在文章的顶部或底
部点击 讨论来访问论坛)。
如果您是在 1997 年之前开始学习编程,那么可能您学习的第一种编程语言没有提供透明的垃圾收集。每
一个 new 操作必须有相应的 delete 操作 ,否则您的程序就会泄漏内存,最终内存分配器(memory
allocator )就会出故障,而您的程序就会崩溃。每当利用 new 分配一个对象时,您就得问自己,谁将
删除该对象?何时删除?
别名, 也叫做 ...
内存管理复杂性的主要原因是别名使用:同一块内存或对象具有 多个指针或引用。别名在任何时候都会
很自然地出现。例如,在清单 1 中,在 makeSomething 的第一行创建的 Something 对象至少有四个
引用:
something 引用。
集合 c1 中至少有一个引用。
当 something 被作为参数传递给 registerSomething 时,会创建临时 aSomething 引用。
集合 c2 中至少有一个引用。
清单 1. 典型代码中的别名
Collection c1, c2;
public void makeSomething {
Something something = new Something();
c1.add(something);
registerSomething(something);
}
private void registerSomething(Something aSomething) {
c2.add(aSomething);
}
在非垃圾收集语言中需要避免两个主要的内存管理危险:内存泄漏和悬空指针。为了防止内存泄漏,必须
确保每个分配了内存的对象最终都会被删除。 为了避免悬空指针(一种危险的情况,即一块内存已经被