我在分析器下运行我的应用程序并且内存使用率远高于我预期的值,其中对象在不再需要后仍然存在。其中大多数都在列表对象已脱离上下文的列表中。
垃圾收集器是否需要更长时间才能释放位于列表中的对象,即使列表本身不再被引用?如果是这样的话,如果我在列表中脱离上下文之前调用清单(),它们会更快地释放吗?
谢谢 - 戴夫
答案 0 :(得分:9)
就垃圾收集机制而言,您要问的是 GC根是否优先于被检测为无法访问的所有其他可传递的对象。鉴于标记扫描算法的工作方式,这两者之间没有区别。所有这些垃圾对象都将在同一个传递中标记,并且一个对象的内部可达性从无法访问的对象中对此没有影响。
找到许多仍未被回收的无法访问的对象并不是什么不寻常的事实,它实际上是为了整体应用程序性能的好处:只有当内存分配失败时才会运行GC。如果您担心堆的大小,那么只需减小最大堆大小。这将导致更频繁的垃圾收集。
答案 1 :(得分:3)
如果我们以ArrayList
为例,clear()
方法会执行此操作:
public void clear() {
modCount++;
// Let gc do its work
for (int i = 0; i < size; i++)
elementData[i] = null;
size = 0;
}
基本上,如果列表的List和元素没有在代码中的任何其他位置引用,则实际上不需要调用clear()
(或者至少你没有通过这样做获得任何东西)。您也不需要将null
分配给List变量,因为它会在超出范围之后的某个时刻被垃圾收集(同样,如果列表本身未在其他任何地方引用)。
查看“标记和清除”垃圾收集算法的工作原理:http://wiki.c2.com/?MarkAndSweep
答案 2 :(得分:1)
是。 clear
将删除对列表中对象的引用,至少列表的ArrayList
实现将这样做。但是,如果您的整个List
对象无论如何都超出了范围,那么您将无法获得任何收益。
答案 3 :(得分:1)
我知道你得到了答案,但是想澄清一下...如果你的旧版本大小为1 GB,但你只在其中存储了1 MB,那么GC绝对不需要运行。事实上,你现在不希望它运行,因为如果它那么你将会有标记扫描触发的停止世界事件算法(通过标记和重新标记阶段)。
只有在内存有压力时才会触发GC。