Java 收集和垃圾回收器

关于Java Web应用程序中性能的小问题。

让我们假设我有一个有十个对象。List<Rubrique>listRubriquesRubrique

A 包含一个产品列表 ( ) 和一个客户端列表 ( )。RubriqueList<product>listProductsList<Client>listClients

如果我这样做,内存中究竟会发生什么:

listRubriques.clear(); listRubriques = null;

我的观点是,由于是空的,因此此列表以前引用的所有对象(包括和)将很快被垃圾回收。但是由于Java中的Collection有点棘手,并且由于我的应用程序存在相当大的性能问题,因此我问的问题是:)listRubriqueslistProductslistClients

编辑:现在让我们假设我的客户端对象包含一个 .因此,我在我的对象之间有一种循环引用。如果我的设置为 ?这一次,我的观点是我的客户端对象将变得“无法访问”,并可能产生内存泄漏?List<Client>listRubriquenull


答案 1

Java 的实际 Sun 实现会不时复制所有被引用/活动的对象。然后,可以从中复制的空间再次用于内存分配。

也就是说,您的示例会损害实际性能。 是不需要的(除非你持有对它的引用),因为listRubrique引用的所有内容都是垃圾,而listRubriques不再被引用。 如果变量 listRubriques 之后超出范围(可能是因为它是一个局部变量,方法在这里结束),也可能不需要。listRubriques.clear()listRubriques = null

不仅不需要调用 clear,因为 clear 会访问以后不再使用的对象的内存,因此会访问该对象,并且现代处理器会将其放入其缓存中。因此,一个死对象显式地进入处理器缓存 - 一些可能更有用的数据将被该操作覆盖。

本文是获取有关 Java 垃圾回收器的更多信息的良好参考。

编辑:对问题中的编辑做出反应:垃圾回收器(至少Sun使用的实现)从一些根引用开始,并复制它可以从此引用到达的所有对象以及复制的对象引用的对象。因此,循环引用的对象是垃圾,因为没有“外部”引用指向它们,内存将在垃圾回收中回收。


答案 2

如果您有:

listRubriques = null;

并且没有其他对象保存对对象的引用或其包含的对象,因此它符合垃圾回收的条件。但是不能保证JVM何时会实际对其运行垃圾回收并释放内存。您可以致电:listRubriques

System.gc();

向JVM推荐您认为此时运行垃圾回收是一个好主意。但即便如此,也不能保证。

还有

listRubriques.clear();

在设置为之前不是必需的。listRubriquesnull

编辑:为了回答您关于循环引用的问题,JVM足够聪明,可以弄清楚整个对象图与任何主动运行的代码断开连接,JVM将正确确定它们都符合垃圾回收的条件。即使在参考计数的糟糕时代,这一直都是如此。现代JVM更快,更高效。但是它们并没有比旧的JVM更多的对象进行垃圾回收。


推荐