Не получив ответа, я решил провести собственное исследование. Я сделал простой тест для проверки GC на SoftReferences.
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).
Результаты довольно интересные: все пробеги проходят просто отлично, кроме одного!
On Android 1.5 device:
testSoftRefsAgainstGc_1() FAILED! AssertionFailedError: expected:0 but was:499
testSoftRefsAgainstGc_2() passed
testSoftRefsAgainstGc_3() passed
testSoftRefsAgainstGc_4() passed
testSoftRefsAgainstGc_5() passed
testSoftRefsAgainstGc_6() passed
testSoftRefsAgainstGc_7() passed
On Android 1.6 device:
testSoftRefsAgainstGc_1() passed
testSoftRefsAgainstGc_2() FAILED! AssertionFailedError: expected:0 but was:499
testSoftRefsAgainstGc_3() passed
testSoftRefsAgainstGc_4() passed
testSoftRefsAgainstGc_5() passed
testSoftRefsAgainstGc_6() passed
testSoftRefsAgainstGc_7() passed
On Android 2.2 device:
All pass.
Эти результаты испытаний стабильны. Я пробовал много раз, и каждый раз это одно и то же. Поэтому я считаю, что это действительно ошибка в сборщике мусора.
ЗАКЛЮЧЕНИЕ
Итак, что мы узнали из этого ... Использование SoftReferences в вашем коде бессмысленно для устройств Android 1.5-1.6 . Для этих устройств вы не получите ожидаемое поведение. Однако я не пробовал 2.1.