0

考虑以下场景:

String dude = "Harold";

//some stuff

dude = "Kumar";

一旦dude被赋予其第二个值“Kumar”,一个与“Harold”分离的全新对象就出现了。我想知道的是,既然“Harold”显然不再有用了,它是立即收集垃圾还是在JVM认为合适的某个时间收集垃圾?

更新:

仅仅因为dude已设置为新值(对象)并不一定意味着对旧对象的所有引用都已被消除。如果另一个引用dude在“Harold”之后和“Kumar”之前调用,它显然会保留“Harold”对象:

String dude = "Harold";

//some stuff

String interim = dude;

dude = "Kumar";

System.out.println("dude = " + dude);
System.out.println("interim = " + interim);

印刷

dude = Kumar
interim = Harold

因此,考虑因素比我最初设想的要多,因此初始值不一定非要在更改后超出范围。

4

7 回答 7

5

没有任何东西可以立即进行垃圾收集,并且不鼓励尝试强制垃圾收集(并且随着每个 java 版本的发布变得越来越困难)。
是的,一旦“Harold”不再可达(没有指向它的指针链),它就有资格进行垃圾收集并且可能被收集(如果 GC 曾经运行过)。话虽如此,字符串可以分配在 const 池中,该池位于 perm gen 中并且不是 GC'ed*(至少在 java 7 之前)。此处有关实习字符串的更多信息:http: //www.codeinstructions.com/2009/01/busting-javalangstringintern-myths.html

* - 不完全准确,即使它在 perm gen 中,const 池也是 GC'ed。情况很复杂。

于 2013-02-12T16:06:58.943 回答
2

因为显然“Harold”不再有用了

你是怎么得出这个结论的?仅通过查看您引用的单个类?但是根据Java Language Specification,在以下情况下会重用字符串文字

  • 同一包中同一类中的文字字符串表示对同一 String 对象的引用。
  • 同一包中不同类中的文字字符串表示对同一 String 对象的引用。
  • 不同包中不同类中的文字字符串同样表示对同一 String 对象的引用。
  • 由常量表达式计算的字符串在编译时计算,然后将它们视为文字。
  • 在运行时通过连接计算的字符串是新创建的,因此是不同的。
  • 显式实习计算字符串的结果是与任何具有相同内容的预先存在的文字字符串相同的字符串。

因此,除非您确定以上所有内容都不正确,否则您可能无法指望它甚至有资格进行垃圾收集。

于 2013-02-12T16:52:24.043 回答
2

通常垃圾收集不会立即发生。此外,字符串是不可变的,并且保存在一个全局表中(据我所知,大多数 JVM),所以它可能永远不会被收集。

于 2013-02-12T16:07:29.453 回答
2

这个:“在以后的某个时间,当 JVM 认为它合适时”。垃圾收集会消耗 CPU 并可能意味着暂停线程。GC 是极其复杂的东西,它不断地平衡 CPU 和内存的使用。

正如其他人所说,字符串更复杂,但我假设您只是想一般地了解 java 对象。我不认为所有关于 String 的华夫饼与您的问题真正相关,并且使这个问题比它需要的复杂得多!

于 2013-02-12T16:12:15.130 回答
1

让我们忘记,该常量String可能会以不同的方式处理。对象没有立即被垃圾回收的主要原因是可能有其他对它的引用。例如,如果您的“某些东西”包含如下语句

t = dude;

当您为 分配新值时,该对象并非不可访问dude。找出所有参考是相当昂贵的,因此只在必要时进行。

于 2013-02-12T16:14:09.603 回答
1

虽然 Java 规范的几乎所有当前实现都使用跟踪垃圾收集器,但我不认为规范要求使用跟踪 GC 管理堆。

可以想象 GC 实现包含引用计数。在上述情况的变体中(旨在避免 const 池细节):

String dude = new String("Harold");
//
dude = new String("Kumar");

的 ref 计数引用的原始对象dude变为零,并且可以立即被垃圾回收。

净点是——对于Java,没有保证,但通常你不必担心。

此外,还有一篇关于 Java GC 的旧参考

于 2013-02-12T16:19:39.830 回答
0

Stringimmutable。当您重新分配变量时,dude = "Kumar"较旧的字符串对象会超出范围。

当垃圾收集器开始工作时,它收集了那个对象。

于 2013-02-12T16:06:46.540 回答