It seams that Dalvik\'s garbage collector doesn\'t respect SoftReferences and removes them as soon as possible, just like WeakReferences. I\'m not 100% sure yet, but despite the
After not receiving an answer I decided to make my own study. I've made a simple test to exercise the GC against 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> list = new ArrayList>(SR_COUNT);
for (int i = 0; i < SR_COUNT; ++i) {
list.add(new SoftReference(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 ref : list) {
if (ref.get() == null) {
++dead;
}
}
assertEquals(0, dead);
}
}
The idea is that I make few runs of the same code increasing stress on SoftReferences each time (by running more GC passes).
Results are pretty interesting: All runs pass just fine except for one!
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.
These test results are stable. I've tried many times and every time it is the same. So I believe it is indeed a bug in garbage collector.
So, what we learn out of this... Using SoftReferences in your code is pointless for Android 1.5-1.6 devices. For these devices you will not get the behavior you expect. I didn't try for 2.1, however.