什么时候'参考对象'可以回收?

时间:2011-09-14 09:32:00

标签: java jvm heap

现在,我遇到了一个奇怪的案例:

public class SoftRefDemo {

     private static List<SoftReference<String>> cache;

     public static void main(String[] args) {
         int total = 3000000;
         cache = new ArrayList<SoftReference<String>>(total);
         for (int i = 0; i < total; i++) {
             cache.add(new SoftReference<String>("fafsfsfsdf" + i));
         }

         System.out.println(cache.size());
     }

}

我已设置JVM设置:-Xms20m -Xmx40m。当我想将许多SoftReference放入缓存时,JVM退出时没有任何提示或异常。实际上,我怀疑SoftReference的动作,它是JVM的特殊对象。谁能解释这个项目会发生什么?

另外两个问题: 1.对于JVM堆中的那些“特殊引用实例”,是否有额外的内存分配方法? 2.什么时候这些引用实例可以在它们指向的实例被释放时被释放?非常感谢!

2 个答案:

答案 0 :(得分:1)

  

当OOM发生时,总有很多SoftReference实例存在,你能帮忙解释一下这种情况吗?

SoftReference的每个实例本身占用24个字节的堆内存(32位Sun JVM也是如此,其他VM可能会有所不同)。您试图在列表中存储3'000'000个实例,这意味着您将需要至少~70Mb的堆空间来存储SoftReference个对象。

SoftReference对象保持对软可到达对象的“软引用”(在您的情况下为String),并且JVM规范保证在虚拟机引发之前将清除这些引用(即String对象将被垃圾回收) OutOfMemoryError。但是JVM将 NOT 垃圾收集SoftReference对象,因为您从cache列表中保留了对它们的强引用。 (因此,如果您需要从堆中删除SoftReference对象 - 将其从cache列表中删除)。

答案 1 :(得分:0)

如果我使用-mx40m

运行此程序
char[] chars = new char[4096];
List<SoftReference<String>> strings = new ArrayList<SoftReference<String>>();
do {
  strings.add(new SoftReference<String>(new String(chars)));
} while(strings.get(0).get()!=null);
int nulls=0, set=0;
for (SoftReference<String> string : strings) {
  if(string.get() == null) nulls++; else set++;
}
System.out.println("nulls= "+nulls+", was still set= "+set);

我得到了

nulls= 4618, was still set= 1

WeakReferences和SoftReferences的一个问题是它们一次都被清除。


尝试WeakReference,SoftReferences只有在必须时才会清楚。要更清楚地看到它们,请尝试创建足够大的数组来触发OutOfMemoryError。

  1. 所有对象都在堆中。甚至静态字段也包含在堆上的伪对象中。 (这个后来的行为没有定义,但我看到它是如何工作的)

  2. 引用实例在被丢弃后被释放(与任何其他对象一样)