SoftReference - почему это не работает? [Дубликат]

Если вы получаете это сообщение во время сохранения или компиляции сборки, просто закройте все файлы, а затем откройте любой файл для компиляции и сохранения.

Для меня причина в том, что я переименовал файл, и старый файл все еще был открыт.

17
задан Dave L. 29 March 2012 в 20:47
поделиться

5 ответов

Похоже, он может быть настроен, но это не так. Конкурирующий маркер-развертка зависает при реализации кучи по умолчанию 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 используются изолированно. Они обычно используются в объектах, где проект должен иметь несколько ссылок на объект, но только одна ссылка должна быть очищена для запуска сбора мусора (для удобства обслуживания контейнера или выполнения времени выполнения, не требующего поиска дорогих ссылок) .

6
ответ дан Edwin Buck 26 August 2018 в 14:41
поделиться

Независимо от ответа, полагаясь на определенную стратегию, ваше программное обеспечение будет ненадежным, поскольку каждая реализация JVM может отличаться. Даже для данной JVM настройка его по-разному может изменить точную стратегию и сломать ваше программное обеспечение. Короче говоря, ошибка заключается в том, чтобы полагаться на определенную стратегию.

Каким ресурсом является управление вашим кешем? Если его чистый кусок выделяет объект, тогда стратегия не должна иметь значения. Использование ReferenceQueue может помочь вам получить уведомление, когда SoftReference будет очищено.

Если тип ресурса не является только выделенным кучей объектом, тогда вы должны потребовать от своих пользователей вызова метода явной освобождения, т. Е. Closeable.close (). Чтобы защитить от «забытых» вызовов этого метода выпуска, вы можете рассмотреть возможность применения метода finalize (), но остерегайтесь его побочных эффектов. Для получения дополнительной информации об этом, я рекомендую прочитать «Пункт 7: Избегайте финализаторов» из «Эффективной Java (2-го издания) Джошуа Блоха».

3
ответ дан Christian Schlichtherle 26 August 2018 в 14:41
поделиться

Нашел одну часть информации в FAQ HotSpot, который может быть устаревшим: http://www.oracle.com/technetwork/java/hotspotfaq-138619.html#gc_softrefs

Что определяет, когда объекты с мягкой ссылкой сброшены?

Начиная с 1.3.1, объекты с мягкой досягаемостью останутся в живых в течение некоторого времени после последнего обращения к ним. Значение по умолчанию - одна секунда продолжительности жизни за один мегабайт в куче. Это значение можно настроить с помощью флага -XX: SoftRefLRUPolicyMSPerMB, который принимает целочисленные значения, представляющие миллисекунды. Например, чтобы изменить значение от одной секунды до 2,5 секунд, используйте этот флаг:

-XX: SoftRefLRUPolicyMSPerMB = 2500

Виртуальная машина Java HotSpot использует максимально возможный размер кучи ( как установлено с опцией -Xmx), чтобы вычислить свободное пространство.

Клиент Java Hotspot Client VM использует текущий размер кучи для вычисления свободного пространства.

Это означает, что общая тенденция для VM сервера Server вырастить кучу, а не скрывать мягкие ссылки, и поэтому -Xmx оказывает значительное влияние, когда мягкие ссылки собираются в мусор.

С другой стороны, клиентская VM будет иметь больший склонность скрывать мягкие ссылки, а не вырастить кучу.

Поведение, описанное выше, верно для 1.3.1 через Java SE 6 версий виртуальных машин Java HotSpot. Однако это поведение не является частью спецификации VM и может быть изменено в будущих выпусках. Подобным же образом флаг -XX: SoftRefLRUPolicyMSPerMB не может присутствовать в какой-либо данной версии.

До версии 1.3.1 виртуальные машины Java HotSpot очищали мягкие ссылки всякий раз, когда они находили их.

Более подробная информация доступна по адресу: http://jeremymanson.blogspot.com/2009/07/how-hotspot-decides-to-clear_07.html (любезно предоставлено комментарием MiserableVariable)

2
ответ дан Dave L. 26 August 2018 в 14:41
поделиться

Не то, чтобы это было авторитетно, но используя SoftReference в гневе, я никогда не видел, чтобы VM их скрывала, а не увеличивала размер VM. На самом деле я почему-то предполагал, что это так, и дизайн очень сильно зависит от этого. У меня были те же -ms и -mx, но это не имеет значения.

Но я не могу найти никакой спецификации, которая на самом деле говорит, что это необходимо. Этот блог , похоже, очень подробно описывает, как SoftReferences покраснели. Из быстрого чтения действительно кажется, что они могут быть очищены, даже если доступна другая память.

2
ответ дан Miserable Variable 26 August 2018 в 14:41
поделиться

Просто мозговой штурм. Если вы хотите, чтобы ваш кеш очистился до другого кеша, возможно, вы можете связать их? Возможно, поддерживая сильную ссылку на записи во втором кеше и освобождая только те ссылки, когда члены вашего собственного кеша очищаются?

Кажется свернутым. Вероятно, я бы склонялся к тому, чтобы просто признать, что оба кэша - это именно то, кэш. Недостатки кэша могут быть болезненными для производительности, но по крайней мере у вашего программного обеспечения не будет сложной стратегии управления кешем.

0
ответ дан Tim Bender 26 August 2018 в 14:41
поделиться
Другие вопросы по тегам:

Похожие вопросы: