[英]Java SoftReference guarantee failing
JDK 7文檔有關於SoftReference
說法:
“在虛擬機拋出OutOfMemoryError之前, 保證可以清除對軟可訪問對象的所有軟引用。”
但是,在我的測試程序中,我一直看到OutOfMemoryError
(除了下面的'Stranger Behavior'部分) :
// RefObjectTest.java
import java.util.*;
import java.lang.ref.*;
public class RefObjectTest {
public static void main(String[] args) {
ArrayList<byte[]> leaks = new ArrayList<>();
byte[] obj = new byte[10 * 1024 * 1024];
SoftReference<byte[]> ref = new SoftReference<>(obj);
// WeakReference is supposed to be eagerly GC'ed, but I see no
// difference in terms of program behavior: still get OOME.
//
// WeakReference<byte[]> ref = new WeakReference<>(obj);
obj = null;
while(true) {
byte[] x = ref.get();
if(x == null) {
System.out.println("Referent stands garbage collected!!");
break;
} else {
System.out.println("Referent still alive.");
}
// Leak memory in small, 10k increments. If soft reference
// worked the way it's advertized, then just before the OOME, the
// 10MB referent should have been GC'ed to accomodate this small
// 10K new memory request. But it doesn't appear to work that way!
// try {
leaks.add(new byte[10 * 1024]);
// } catch(OutOfMemoryError e) {
// System.out.println(ref.get() == null ? "Referent cleared" :
// "Referent still alive");
// }
// VERY STRANGE: If I re-instate the above try-catch block, then no OOME is
// thrown, and the program keeps printing "Referent still alive" lines
// forever until I finally kill it with a Ctrl+C.
// Uncommenting gc() tends to delay the OOME in terms of time,
// but OOME eventually does happen, and after the same number of
// iterations of this loop.
//
// System.gc();
}
}
}
這是輸出:
$ java -Xmx15m RefObjectTest
Referent still alive.
...
Referent still alive.
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
at RefObjectTest.main(RefObjectTest.java:38)
陌生人的行為
什么是非常奇怪的是,如果我重新啟動try-catch塊,該程序似乎永遠運行正常,打印“Referent仍然活着”。 直到我累了並殺了它。
$ java -version
java version "1.7.0_45"
Java(TM) SE Runtime Environment (build 1.7.0_45-b18)
Java HotSpot(TM) 64-Bit Server VM (build 24.45-b08, mixed mode)
$
$ uname -a
Linux ida 3.10.11-100.fc18.x86_64 #1 SMP Mon Sep 9 13:06:31 UTC 2013 x86_64 x86_64 x86_64 GNU/Linux
我在這一切中缺少什么?
這一點都不奇怪,分配失敗就是拋出異常。 通過捕獲異常,你說程序可以繼續,通過不捕獲異常,你說你無法處理它並退出程序。
在你的while循環中你正在做:
byte[] x = ref.get();
這是從您的軟參考創建一個新的強引用。 一旦你這樣做,它就不再有資格收集。 在繼續執行新分配之前,您不會清除強引用。
完成測試后, x = null
。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.