Ответ 1
Похоже, он может быть настроен, но это не так. Совпадающий сборщик меток зависает при реализации кучи по умолчанию must_clear_all_soft_refs()
, который, по-видимому, только true
при выполнении _last_ditch_collection
.
bool GenCollectedHeap::must_clear_all_soft_refs() {
return _gc_cause == GCCause::_last_ditch_collection;
}
В то время как обычная обработка неудачного распределения имеет три последовательных вызова метода кучи do_collect
, в CollectorPolicy.cpp
HeapWord* GenCollectorPolicy::satisfy_failed_allocation(size_t size,
bool is_tlab) {
Что пытается собрать, пытается перераспределить, пытается развернуть кучу, если это не удастся, а затем, как последнее усилие, пытается собрать очищающие ссылки.
Комментарий к последней подборке довольно полезен (и единственный, который вызывает очистку мягких ссылок)
// If we reach this point, we're really out of memory. Try every trick
// we can to reclaim memory. Force collection of soft references. Force
// a complete compaction of the heap. Any additional methods for finding
// free memory should be here, especially if they are expensive. If this
// attempt fails, an OOM exception will be thrown.
{
IntFlagSetting flag_change(MarkSweepAlwaysCompactCount, 1); // Make sure the heap is fully compacted
gch->do_collection(true /* full */,
true /* clear_all_soft_refs */,
size /* size */,
is_tlab /* is_tlab */,
number_of_generations() - 1 /* max_level */);
}
--- Отредактировано в ответ на очевидное, я описывал слабые ссылки, а не мягкие ---
На практике я бы предположил, что SoftReferences являются "не", когда JVM вызывается для сбора мусора в ответ на попытки избежать OutOfMemoryError
.
Для SoftReference
для совместимости со всеми четырьмя сборщиками мусора Java 1.4 и с новым сборщиком G1 решение должно лежать только с определением достижимости. К тому моменту, когда возникают жатвы и уплотнения, слишком поздно решить, доступен ли объект. Это предполагает (но не требует), что существует "контекст" коллекции, который определяет доступность, основанную на доступности свободной памяти в куче. Такой контекст должен был бы указать не следовать SoftReference
, прежде чем пытаться следовать им.
Поскольку OutOfMemoryError
сбор мусора избегания специально запланирован в режиме полной коллекции, остановившись в мире, было бы нелегко представить сценарий, когда менеджер кучи устанавливает "не следует SoftReference
", перед созданием коллекции.
--- Хорошо, поэтому я решил, что ответ "должен работать таким образом" просто не был достаточно хорошим.
Из исходного кода src/share/vm/gc_implementation/concurrentMarkSweep/vmCMSOperations.cpp (основные моменты мои)
Операция на самом деле "делать" сбор мусора:
170 void VM_GenCollectFullConcurrent::doit() {
Нам лучше быть потоком VM, иначе "программный" поток - сбор мусора!
171 assert(Thread::current()->is_VM_thread(), "Should be VM thread");
Мы являемся параллельным сборщиком, поэтому лучше планировать его одновременно!
172 assert(GCLockerInvokesConcurrent || ExplicitGCInvokesConcurrent, "Unexpected");
173
Возьмите кучу (в ней есть объект GCCause).
174 GenCollectedHeap* gch = GenCollectedHeap::heap();
Проверьте, нужна ли нам передняя "молодая" коллекция
175 if (_gc_count_before == gch->total_collections()) {
176 // The "full" of do_full_collection call below "forces"
177 // a collection; the second arg, 0, below ensures that
178 // only the young gen is collected. XXX In the future,
179 // we'll probably need to have something in this interface
180 // to say do this only if we are sure we will not bail
181 // out to a full collection in this attempt, but that's
182 // for the future.
Не связаны ли потоки программы с кучей?
183 assert(SafepointSynchronize::is_at_safepoint(),
184 "We can only be executing this arm of if at a safepoint");
Извлеките причину сбора мусора (причина этой коллекции) из кучи.
185 GCCauseSetter gccs(gch, _gc_cause);
Сделайте полную коллекцию молодого пространства
Обратите внимание, что его пропуски в значении кучи must_clear_all_soft_refs В сценарии OutOfMemory должно быть установлено значение true, и в любом случае направляет "do_full_collection", чтобы не следовать мягким ссылкам
186 gch->do_full_collection(gch->must_clear_all_soft_refs(),
187 0 /* collect only youngest gen */);
_gc_cause - это перечисление, которое (догадки здесь) установлено на _allocation_failure
в первой попытке избежать OutOfMemoryError
и _last_ditch_collection
после этого не удалось (попытаться собрать временный мусор)
Быстрый просмотр в памяти "кучи" модуля показывает, что в do_full_collection
, который вызывает do_collection
, мягкие ссылки очищаются явно (в "правильные" условия) с линией
480 ClearedAllSoftRefs casr(do_clear_all_soft_refs, collector_policy());
--- Оригинальный пост следует тем, кто хочет узнать о слабых ссылках ---
В методе Mark and Sweep Soft-ссылки не следуют из основного потока (и, таким образом, не отмечены, если другая ветка не может достичь этого через немягкие ссылки.
В алгоритме копирования Метки со ссылками на объекты не копируются (снова, если они не достигаются с помощью другой несимметричной ссылки).
В принципе, при следовании сети ссылок из "основного" потока выполнения, мягкие ссылки не соблюдаются. Это позволяет их объектам собирать мусор, как если бы у них не было ссылок, указывающих на них.
Важно отметить, что мягкие ссылки почти никогда не используются изолированно. Они обычно используются в объектах, где проект должен иметь несколько ссылок на объект, но только одна ссылка должна быть очищена для запуска сбора мусора (для удобства обслуживания контейнера или выполнения времени выполнения, не требующего поиска дорогих ссылок).