1

我正在阅读 JVM 中的内存管理,如果一个对象不再引用它,它就会被垃圾收集。可以说,我有一个程序

public test {
  public static void main(String[ ] args) {
      String name = "hello";  
      for (int i =0 ; i < 5; i++) {
         System.out.println(i);
       }
   }
}

如您所见,String name没有在任何地方使用,因此它的引用一直保持在外面,而不是垃圾收集。

我现在有,

String name = "hello"
  String name2 = name.substring(1,4)//"ell"

再一次,对于的引用hello必须始终存在,并且不能被垃圾收集,因为name2使用它。

那么什么时候这些String或任何objects垃圾收集,它们有引用但已经过时,即不再在代码中使用?

我可以看到一个场景,其中修剪数组会导致内存泄漏,因此将其引用设置为 null 是垃圾收集那些过时引用的好方法。

4

3 回答 3

1

从技术上讲,JVM从来不需要垃圾收集对象。在实践中,它们通常会在最后一个引用消失后稍作停留并释放内存。

首先,请注意常量总是存在的。即使您为 分配了一个新值name,系统仍然有一个与该类一起存储的副本,"hello"每次您点击该初始化语句时它都会重用该副本。

但是,不要将使用对象进行某种计算与永久保留对它的引用相混淆。在您的第二个示例中,虽然"hello"实际上被保留了,但这只是因为它生活在常量池中;name2没有任何形式的“保留”可以将其保存在内存中。执行和结束的调用substring,没有永远的等待name。(Oracle JVM 中的实际实现共享底层char[],但这取决于实现。)

清除数组是一种很好的做法,因为它们很容易被长期使用和重用。如果整个数组被垃圾回收,它持有的引用将被删除(如果它们是最后一个对象,它们的对象也会被垃圾回收)。

于 2013-09-05T23:43:21.837 回答
1

I can see one scenario where trimming down an array causes memory leak and hence setting its reference to null is a good way to garbage collect those obsolete references.

Strings are reference types, so all the rules for reference types with respect to garbage collection apply to strings. The JVM may also do some optimizations on String literals but if you're worrying about these, then you're probably thinking too hard.

When does the JVM collect unreferenced objects?

The only answer that matters is: you can't tell and it needn't ever, but if it does you can't know when that will be. You should never write Java code around deterministic garbage collection. It is unnecessary and fraught with ugliness.

Speaking generally, if you confine your reference variables (including arrays or collections of reference types) to the narrowest possible scope, then you'll already have gone a long way toward not having to worry about memory leaks. Long-lived reference types will require some care and feeding.

"Trimming" arrays (unreferencing array elements by assigning null to them) is ONLY necessary in the special case where the array represents your own system for managing memory, eg. if you are making your own cache or queue of objects.

Because the JVM can't know that your array is "managing memory" it can't collect unused objects in it that are still referenced but are expired. In cases where an array represents your own system for managing memory, then you should assign null to array elements whose objects have expired (eg. popped off a queue; J. Bloch, Essential Java, 2nd Ed.).

于 2013-09-06T00:31:20.870 回答
0

Java 中的每个变量都有一个作用域:定义变量的一段代码。像您的示例中那样的局部变量的范围在它所name在的括号之间{}。因此,name变量将在线程到达String name = "hello";声明时定义,并将保持活动状态直到main方法完成(因为括号中的变量是关闭)。

字符串与其他变量不同。字符串在内部缓存,实际上可能还不能用于垃圾收集器。

于 2013-09-05T23:42:18.073 回答