答えが返ってこなかったので、自分で勉強することにしました。SoftReferencesに対してGCを実行するための簡単なテストを行いました。
public class TestSoftReference extends TestCase {
public void testSoftRefsAgainstGc_1() { testGcWithSoftRefs(1); }
public void testSoftRefsAgainstGc_2() { testGcWithSoftRefs(2); }
public void testSoftRefsAgainstGc_3() { testGcWithSoftRefs(3); }
public void testSoftRefsAgainstGc_4() { testGcWithSoftRefs(4); }
public void testSoftRefsAgainstGc_5() { testGcWithSoftRefs(5); }
public void testSoftRefsAgainstGc_6() { testGcWithSoftRefs(6); }
public void testSoftRefsAgainstGc_7() { testGcWithSoftRefs(7); }
private static final int SR_COUNT = 1000;
private void testGcWithSoftRefs(final int gc_count) {
/* "Integer(i)" is a referrent. It is important to have it referenced
* only from the SoftReference and from nothing else. */
final ArrayList<SoftReference<Integer>> list = new ArrayList<SoftReference<Integer>>(SR_COUNT);
for (int i = 0; i < SR_COUNT; ++i) {
list.add(new SoftReference<Integer>(new Integer(i)));
}
/* Test */
for (int i = 0; i < gc_count; ++i) {
System.gc();
try {
Thread.sleep(200);
} catch (final InterruptedException e) {
}
}
/* Check */
int dead = 0;
for (final SoftReference<Integer> ref : list) {
if (ref.get() == null) {
++dead;
}
}
assertEquals(0, dead);
}
}
アイデアは、同じコードを数回実行するだけで、毎回SoftReferencesへのストレスが増えるということです(より多くのGCパスを実行することによって)。
結果は非常に興味深いものです。1つを除いて、すべての実行が問題なく通過します。
Android 1.5デバイスの場合:
testSoftRefsAgainstGc_1()が失敗しました!AssertionFailedError:expected:0しかしwas:499
testSoftRefsAgainstGc_2()に合格
testSoftRefsAgainstGc_3()に合格
testSoftRefsAgainstGc_4()に合格
testSoftRefsAgainstGc_5()に合格
testSoftRefsAgainstGc_6()に合格
testSoftRefsAgainstGc_7()に合格
Android 1.6デバイスの場合:
testSoftRefsAgainstGc_1()に合格
testSoftRefsAgainstGc_2()が失敗しました!AssertionFailedError:expected:0しかしwas:499
testSoftRefsAgainstGc_3()に合格
testSoftRefsAgainstGc_4()に合格
testSoftRefsAgainstGc_5()に合格
testSoftRefsAgainstGc_6()に合格
testSoftRefsAgainstGc_7()に合格
Android 2.2デバイスの場合:
すべて合格。
これらのテスト結果は安定しています。私は何度も試しましたが、毎回同じです。ですから、それは確かにガベージコレクターのバグだと思います。
結論
したがって、これから学んだこと...コードでSoftReferencesを使用することは、Android 1.5〜1.6デバイスでは無意味です。これらのデバイスでは、期待する動作は得られません。しかし、私は2.1を試しませんでした。