在尝试使用串行GC 的Java内存使用时,我注意到随着java.util.LinkedList<String>
中节点数量的增加,堆不仅增长了,而且非堆内存用法也在不断增长。但是,对于ArrayList
,只有堆增长,非堆内存随着堆的增长而保持不变。
为了测试这个,我运行了一个简单的程序,它会在无限循环中向LinkedList添加String
个节点,当它抛出时(通过-XX:MaxHeapSize
标志控制)OutOfMemoryError
它会在catch块内无限循环。除了-XX:MaxHeapSize
标志之外,我还使用了-XX:MaxMetaSpaceSize
,-XX:ReservedCodeCacheSize
和-Xshare=on
标志,这些标志对此行为没有任何影响。我用不同的MaxHeapSize值保持它们的值不变。我还打开了Native Memory Tracking。我用ArrayList而不是LinkedList重复了相同的程序。为了测量堆内存使用情况,我注意到了NMT报告的已提交堆。为了获得非堆内存,我从smem
报告的RSS中减去了堆内存。
该实验在 HotSpot 64位服务器VM 25.144-b01 和 OpenJDK 64位服务器VM 25.131-b11 上重复,并且具有类似的结果。
以下是我使用OpenJDK服务器VM记录的值(以MB为单位)。
对于LinkedList:
| MaxHeapSize | Heap | Non-heap |
| ----------- | ---- | -------- |
| 108.8 | 110 | 78.6 |
| 217.6 | 218 | 122.5 |
| 435.2 | 436 | 161.1 |
| 870.4 | 872 | 366.6 |
| 1305.6 | 1306 | 470.2 |
对于ArrayList:
| MaxHeapSize | Heap | Non-heap |
| ----------- | ---- | -------- |
| 108.8 | 110 | 34.0 |
| 217.6 | 218 | 32.6 |
| 435.2 | 436 | 33.4 |
| 870.4 | 872 | 37.2 |
| 1305.6 | 1306 | 37.7 |
查看java.utils.LinkedList<E>
类的实现并不表示可能导致此行为的任何内容。
什么可能导致LinkedList和ArrayList之间的内存使用情况有所不同?