G1不处理软引用

时间:2015-06-10 19:46:12

标签: java garbage-collection g1gc

这是我的简单gc测试:

The score is: <span class="score"><span style="width: 88%"></span></span>

使用这些参数(启用G1):

public class Main {

  static class Data {
    public long[] l = new long[100];
  }

  static List<SoftReference<Data>> list = new ArrayList<>();

  public static void main(String[] args) {
    long i = 0;

    while (true) {
      list.add(new SoftReference<>(new Data()));
      ++i;
      if (i % 1000 == 0) {
        sleep(1);
        if (i % 1_000_000 == 0)
          sleep(1000);
      }
    }
  }

  static void sleep(long millis) {
    try { Thread.sleep(millis); } catch (InterruptedException ignored) {}
  }
}

我grep输出:

java -Xmx2G -Xms2G -XX:MaxPermSize=128m -XX:+PrintGCDetails -XX:+PrintGCTimeStamps 
-XX:+PrintAdaptiveSizePolicy -Xloggc:jvm.log -XX:+UseG1GC 
-XX:InitiatingHeapOccupancyPercent=5 Main

得到这样的东西:

grep -E "(Full|GC cleanup)" jvm.log

似乎在ParallelGc的完整集合期间收集了软引用,而并发集合几乎无用。 VisualVm的堆转储也证明了这个版本。

我错过了什么或者它是G1中的错误吗?

检查1.7.0_51-b13和1.8.0_45-b15 x64。

2 个答案:

答案 0 :(得分:3)

也许你对弱引用感到困惑?

GC不会被迫收集软参考,除非它发现自己处于严重的内存压力下。

有关详细信息,请参阅here

特别注意文档中的以下引用:

  

软件引用对象,它们在垃圾收集器的自由裁量权中被清除以响应内存需求。

文档提供的唯一真正保证如下:

  

在虚拟机抛出OutOfMemoryError之前,保证已清除对软可访问对象的所有软引用。

答案 1 :(得分:1)

Undefined variable(默认值= 1000)控制软引用的收集率。较低的值使其更快地收集它们。

我不知道它是如何与G1的区域相互作用的。有些地区很少被触及,因此不会考虑它们的软参考。

正如@sstan所提到的,WeakReferences可能会提供更可预测的行为,但代价是参考文件的生命周期要短得多。

另一个问题是您没有清除已排除的软引用对象列表。如果使用reference queue注册refs,在睡眠(1000)之后轮询该队列以进行引用并从列表中删除它们,则不应该耗尽内存。 为了更快地查找,集合可能比列表更合适。