以前分配的对象的垃圾收集

时间:2013-02-12 16:03:54

标签: java garbage-collection

考虑以下情况:

String dude = "Harold";

//some stuff

dude = "Kumar";

一旦dude被赋予其第二个值“Kumar”,就会出现一个与“Harold”分开的全新对象。我想知道的是,因为“哈罗德”显然没有用,它是立即收集垃圾还是在JVM认为合适的时候收集?

更新

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

因此,有比我最初想象的更多的考虑因素,因此初始值不一定必须在更改后超出范围。

7 个答案:

答案 0 :(得分:5)

不会立即对垃圾进行垃圾收集,并且不鼓励尝试强制进行垃圾收集(并且每次发布java时都会变得越来越困难)。
是的,分钟“Harold”不再可达(没有指针链通向它)它有资格进行垃圾收集并可能被收集(如果GC运行)。话虽如此,可以在const池中分配字符串,它位于perm gen中并且不是GC *(至少直到java 7)。有关实习字符串的更多信息:http://www.codeinstructions.com/2009/01/busting-javalangstringintern-myths.html

* - 不完全准确,即使它处于perm gen,const池仍然是GC。它很复杂。

答案 1 :(得分:2)

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

答案 2 :(得分:2)

这一个:“在JVM认为合适的某个时候”。 垃圾收集花费CPU,可能意味着暂停线程。 GC是一个非常复杂的东西,不断平衡CPU与内存的使用。

正如其他人所说,字符串更复杂,但我想你一般都想知道java对象。 我不认为关于String的所有这些问题都与你的问题非常相关,并使这个问题变得比它需要的复杂得多!

答案 3 :(得分:2)

  

因为“Harold”显然没有任何用处

你是如何得出这个结论的?只是通过查看您参考的单个班级?但是根据the Java Language Specification,在以下情况下重用字符串文字

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

因此,除非你确定上述所有情况都不正确,否则你可能不会指望它甚至有资格进行垃圾收集。

答案 4 :(得分:1)

让我们忘记,常数String可能会有不同的处理方式。对象未立即进行垃圾回收的主要原因是可能存在其他引用。例如,如果您的“某些内容”包含类似

的语句
t = dude;

将新值分配给dude时,无法访问该对象。要找出所有参考资料的成本相当高,因此只在必要时才进行。

答案 5 :(得分:1)

虽然几乎每个Java规范的实现都使用跟踪垃圾收集器,但我不相信规范要求使用跟踪GC来管理堆。

可以想象GC实现包含引用计数。在上述情况的这种变化中(为避免const池细节而设计):

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

dude引用计数引用的原始对象变为零,可能立即被垃圾收集。

关键是 - 使用Java,没有保证,但通常你不必担心它。

另外,old reference that talks about Java GC

答案 6 :(得分:0)

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

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