Похоже, он может быть настроен, но это не так. Конкурирующий маркер-развертка зависает при реализации кучи по умолчанию 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
s был совместим со всеми четырьмя сборщиками мусора Java 1.4 и с новым сборщиком G1, решение должно лежать только с определением достижимости. К тому моменту, когда возникают жатвы и уплотнения, слишком поздно решить, доступен ли объект. Это предполагает (но не требует), что существует «контекст» коллекции, который определяет доступность, основанную на доступности свободной памяти в куче. Такой контекст должен был бы указывать, что не следует SoftReference
s до попытки следовать им.
Поскольку сбор OutOfMemoryError
уклонения от уклонения специально запланирован в режиме полной коллекции, stop-the-world, было бы сложно представить сценарий, когда менеджер кучи устанавливает флаг «не следует за 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();
Check чтобы увидеть, нужна ли нам передняя «молодая» коллекция
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 и Sweep мягкие ссылки - not следуют из основного потока (и thu s не помечены, если другая ветвь не может достигнуть ее через немягкие ссылки.
В алгоритме копирования Метки, ссылающиеся на объекты, указывают на не , скопированные (снова, если они не будут достигнуты
В основном, если следовать за сетью ссылок из «основного» потока выполнения, мягкими ссылками являются , а не . Это позволяет их объектам собирать мусор, как если бы у них не было ссылок, указывающих на них.
Важно отметить, что мягкие ссылки почти never используются изолированно. Они обычно используются в объектах, где проект должен иметь несколько ссылок на объект, но только одна ссылка должна быть очищена для запуска сбора мусора (для удобства обслуживания контейнера или выполнения времени выполнения, не требующего поиска дорогих ссылок) .