jvm 什么时候可以回收“引用对象”?

olqngx59  于 2022-11-23  发布在  其他
关注(0)|答案(2)|浏览(134)

现在,我遇到了这样一个奇怪的情况:

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设置:-Xms 20 m-Xmx 40 m。当我想把很多SoftReference放到缓存中时,JVM没有任何提示或异常就退出了。实际上,我对SoftReference的行为表示怀疑,它是JVM的特殊对象。有人能解释一下这个程序发生了什么吗?

**另外两个问题:**1. JVM堆中的那些“特殊引用示例”是否有额外的内存分配方法?2.当那些引用示例所指向的示例被释放后,它们什么时候才能被释放?谢谢!

q8l4jmvw

q8l4jmvw1#

当出现对象模型时,总是有很多SoftReference示例已经存在,你能帮助解释这种情况吗?
SoftReference的每个示例本身占用24字节的堆内存(这对于32位Sun JVM是真实的,对于其他VM可能会有所不同)。您尝试在列表中存储3 '000'000个示例,这意味着您将至少需要~ 70 Mb的堆空间来存储SoftReference对象。
SoftReference对象保留对软可访问对象的“软引用(本例中为字符串),JVM规范保证将清除这些引用(即字符串对象将被垃圾收集)。但是,JVM不会对SoftReference对象进行垃圾收集,因为您保留了cache列表中对它们的强引用。(因此,如果您需要从堆中删除SoftReference对象,请从cache列表中删除它)。

qrjkbowd

qrjkbowd2#

如果我用-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.所有对象都在堆中。甚至静态字段也被 Package 在堆中的伪对象中。(后面的行为没有定义,但我已经看到它是如何工作的)
1.引用示例在被丢弃后被释放(与任何其他对象一样)

相关问题