Есть много вещей, которые могут происходить, но в отношении вашей тестовой программы, использующей мягкие значения: вы можете получить OutOfMemoryError, даже если у вас есть SoftReferences, которые еще не были собраны сборщиком мусора. Это повторяется: вы можете получить ошибку OutOfMemoryError, даже если у вас есть SoftReferences, которые еще не очищены.
SoftReferences немного странные, см. http://jeremymanson.blogspot.com/2009/07/how-hotspot-decides-to-clear_07.html для описания текущей механики. Вероятно, в вашем тестовом случае GC просто не успел сделать два полных GC.
Когда вы использовали слабые клавиши, компьютерная графика сразу их очищала, и ей не пришлось ждать полной паузы. (б / с Слабые ссылки собираются агрессивно.)
По моему мнению, если вы хотите кэш с чувствительностью к памяти с целочисленными ключами, я думаю, что уместно следующее:
data = new MapMaker().softValues().makeMap();
Вы можете легко создать тестовую программу, которая выдает OutOfMemoryError, но если ваше реальное приложение несколько хорошо себя ведет и не испытывает слишком большого давления, вы можете быть в порядке. SoftReferences довольно сложно понять правильно.
Если вам нужно использовать System.gc () во избежание нехватки памяти, я бы вместо этого рекомендовал вам переключиться на карту LRU с фиксированным максимальным размером (см. Пример javadoc для java.util.LinkedHashMap.) Это не одновременно, но я ожидаю, что в конечном итоге это даст вам лучшую пропускную способность, чем обращение к системе с просьбой выполнить сборку мусора с полной паузой много раз.
Да, и последнее замечание о целочисленных и слабых клавишах (): MapMaker использует сравнение идентификаторов для клавиш при использовании слабых или программных клавиш, и это довольно сложно сделать правильно. Свидетельствуйте следующее:
Map<Integer,String> map = new MapMaker().weakKeys().makeMap();
Integer a = new Integer(1);
Integer b = new Integer(1);
Integer c = 1; //auto box
Integer d = 1; //auto box
map.put(a, "A");
map.put(b, "B");
map.put(c,"C");
map.put(d,"D");
map.size() // size is 3;
Удачи.