这个
ArrayList
类使用简单的策略来管理空间。当列表的后备数组已满且您添加了另一个元素时
阵列列表
分配一个较大的数组,并将元素从旧数组复制到新数组。新阵列的大小将比旧阵列大50%,达到阵列大小的架构限制。以下是Java 8实现:
private void grow(int minCapacity) {
// overflow-conscious code
int oldCapacity = elementData.length;
int newCapacity = oldCapacity + (oldCapacity >> 1);
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
// minCapacity is usually close to size, so this is a win:
elementData = Arrays.copyOf(elementData, newCapacity);
}
在您的示例中,您反复向列表中添加元素,这导致列表的备份数组不断增长。
接下来,a
Reference
类有4个字段(在Java 8中),其中一个字段是
referenent
。。。它指向的对象是
参考
。当
参考
坏了,发生的是
referent
设置为
null
,从而允许对目标对象进行GC(通常在下一个GC循环中……但不一定)。但是
参考
对象本身未被释放。。。除非你让它变得遥不可及。
在您的示例中,您没有做任何事情来
WeakReference
无法访问的对象。相反,它们正在列表中累积。
最终,列表和(断开的)消耗的内存
弱引用
它所持有的对象将填满堆,你会得到一个OOME。(可能会在
Arrays.copyOf
呼叫但在分配
弱引用
或a
Calendar
)
如果您希望列表实际释放空间以响应内存压力,那么需要检测并删除损坏的
弱引用
列表中的对象。这不是小事。
-
你
能够
让每个人排队
弱引用
在a中使用
ReferenceQueue
,并让队列处理器删除每个
弱引用
因为它坏了。然而,这将是低效的,因为列表删除是O(N)。
-
另一个想法是让队列处理器增加一个专用计数器,并让
add
方法使用计数器来决定何时扫描和删除断开的引用。
-
你也应该考虑打电话
ArrayList::trimToSize
。。。或同等产品。。。减少后备存储区大小。但请记住,这会暂时提高内存利用率。
这可能需要自定义
List
实施