1

Integer() 到底有多大?我问是因为下面发生了什么。

在尝试将 10^6 个整数(在 [0, 10^6) 中)放入双端队列后,我用完了堆内存。该实现使用双向链表并显示为

Deque<Item> implements Iterable<Item> { }

但是当使用字符串时,我能够完成而不必增加堆的大小:

String hw = "Hello, world."; 

for (i=0;i<10**6;i++) {
 myDq.addToEnd(hw); 
}
4

1 回答 1

9

hw总是引用同一个对象,所以即使你添加了 10^6 个项目(因此在内部有 ~10^6 个节点),你也只会String分配一个对象——很多对那个对象的引用,但只是那一个对象。

事实上,即使你做了类似的事情:

for (i=0;i<10**6;i++) {
  String hs = "Hello, world."
  myDq.addToEnd(hw); 
}

String由于字符串实习,您只有一个:整个 JVM 中所有相等的字符串文字都使用同一个String对象。

我怀疑如果您将其更改为以下内容,您将获得相同的 OOM:

for (i=0;i<10**6;i++) {
  String hs = new String("Hello, world.".toCharArray());
  myDq.addToEnd(hw); 
}

String每次都会分配一个新的,并带有原始Stringchar 数组的副本。

(OOM 是 的常见昵称OutOfMemoryError,这是 Java 在堆空间用完并且无法通过垃圾收集器 (GC) 回收足够多时抛出的东西。在这种情况下,列表和所有可通过它访问的对象 -内部节点对象、IntegerString值等——程序仍然可以访问,因此无法进行 GC,因此 JVM 无处可去以获得更多堆空间。)

于 2013-09-07T04:50:26.937 回答