2

正如每个 java 开发人员都知道的那样, java 对象在不再使用时将被垃圾收集。我想知道 JVM 如何识别必须选择哪个对象进行垃圾收集。(比如说……如果我有 10 个对象。如果 2 个对象被垃圾收集,那么 10 个对象中 jvm 如何找到这两个对象)。

JVM 使用“标记和扫描”算法(如果我是对的)。

1)例如我在下面提供字符串对象场景

  class Sample{

     public static void main(Strings args[]){
      String s1=new String("10");
      String s2=new String("20");
      String s3=new String("30");
      String s4=new String("40");
      String s5=new String("50");
      String s6=new String("60");
      String s7=new String("70"); 

        s1=null; //now s1 is eligible for gc collection
        s2=null; //now s2 is eligible for collection


 }
}

//现在 s1 和 s2 有资格进行 gc 收集。如果我明确地将引用(s1,s2)变为空,但是在堆上分配的内存会发生什么?它会被释放吗?

4

6 回答 6

2

实际上什么也没有发生。s1 和 s2 使用的内存只有在 GC 开始工作时才会被重用,这只会在 JVM 决定时发生,并且可能永远不会发生。在您的情况下,GC 几乎不会启动。

于 2013-10-03T06:19:45.843 回答
1

如果任何活动线程无法以任何方式访问该对象,那么该对象就有资格进行垃圾回收。但不能保证 GC 运行,因为它取决于 JVM 内部逻辑和算法。通常,当 JVM 认为是时候清理一些内存使用时,就会发生这种情况。在您的情况下,s1 和 s2 有资格获得 GCed,但我们不能说它何时会发生。

于 2013-10-03T06:49:35.463 回答
1

分配null给任何引用都不会释放内存。它仅使引用可用于使用垃圾收集器删除。意味着现在当垃圾收集器运行时,这个引用分配的内存可以是空闲的。

于 2013-10-03T06:15:44.530 回答
1

它在这里相当简洁地介绍:http ://www.brpreiss.com/books/opus5/html/page424.html

标记和清除算法被称为跟踪垃圾收集器,因为它跟踪程序直接或间接访问的整个对象集合。

程序可以直接访问的对象是处理器堆栈上的局部变量以及引用对象的任何静态变量引用的对象。在垃圾收集的上下文中,这些变量称为根。如果对象被其他(直接或间接)可访问对象中的字段引用,则该对象是间接可访问的。

因此,当您这样做时,s1=null;您将断开根,并且相应的实例有资格进行收集。

实际的“收集”(释放堆)发生在 GC 实际执行时。至于何时发生这种情况,并没有一个万能的答案。请参阅Java 中垃圾收集的频率是多少?

于 2013-10-03T06:27:13.370 回答
0

如果无法从任何活动线程或任何静态引用访问对象,则该对象有资格进行垃圾收集或 GC

看这里

于 2013-10-03T06:12:54.197 回答
0

当该对象的引用计数为 0 时,Java 对象有资格进行垃圾回收。引用计数为 0 表示“该特定对象没有被任何变量引用,因此不能再使用它”。垃圾收集器在第一遍标记所有引用计数为 0 的对象,在第二遍中清除所有标记的对象。因此它是标记和扫描算法。

它会被释放吗?

这取决于垃圾收集器,当垃圾收集器在您将 s1 和 s2 设为 null 后重新运行时,它们将有资格进行垃圾收集。但是,将引用设为 null 不会立即从内存中释放对象

于 2013-10-03T06:20:26.500 回答