Проблема в том, что я не могу
надежно получить мягкие ссылки, чтобы быть
очищено.
Это не уникально для SoftReferences. Из-за особенностей сборки мусора в Java нет гарантии, что что-либо, что собирает мусор, будет фактически собрано в любой момент времени. Даже с простым кусочком кода:
Object temp = new Object();
temp = null;
System.gc();
нет никакой гарантии, что объект, созданный в первой строке, является сборщиком мусора в этой или любой другой точке. Это просто одна из вещей, с которыми вам приходится жить на языке, управляемом памятью, вы отказываетесь от декларативной власти над этими вещами. И да, это может усложнить временную проверку на утечки памяти.
Тем не менее, согласно приведенным вами Javadoc, SoftReferences обязательно должны быть очищены до того, как будет выдан OutOfMemoryError (на самом деле, это весь их смысл и единственный способ отличить их от ссылок на объекты по умолчанию). Таким образом, может показаться, что в какой-то мере происходит утечка памяти, когда вы держите более жесткие ссылки на рассматриваемые объекты.
Если вы используете опцию -XX:+HeapDumpOnOutOfMemoryError
для JVM, а затем загружаете дамп кучи в нечто вроде jhat , вы сможете увидеть все ссылки на ваши объекты и, таким образом, увидеть, есть ли любые ссылки, кроме ваших мягких. В качестве альтернативы вы можете добиться того же с помощью профилировщика во время выполнения теста.