现在,我遇到了一个奇怪的案例:
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.什么时候这些引用实例可以在它们指向的实例被释放时被释放?非常感谢!
答案 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。
所有对象都在堆中。甚至静态字段也包含在堆上的伪对象中。 (这个后来的行为没有定义,但我看到它是如何工作的)
引用实例在被丢弃后被释放(与任何其他对象一样)