Гарантирует ли GC, что очищенные ссылки помещаются в очередь ReferenceQueue в топологическом порядке?

StackOverflow https://stackoverflow.com/questions/2497014

Вопрос

Скажем, есть два объекта, A и B, и есть указатель A.x --> B, и мы создаем, скажем, WeakReferenceдля обоих A и B, с ассоциированным ReferenceQueue.

Предположим, что оба A и B стать недостижимым.Интуитивно B нельзя считать недостижимым раньше A является.В таком случае получим ли мы каким-то образом гарантию того, что соответствующие ссылки будут поставлены в очередь в интуитивном (топологическом, когда циклов нет) порядке в ReferenceQueue?Т.е.ref(A) перед ref(B).Я не знаю, а что, если GC пометит кучу объектов как недоступные, а затем поставит их в очередь в произвольном порядке?

я просматривал Финализатор.java гуавы, увидев этот фрагмент:

private void cleanUp(Reference<?> reference) throws ShutDown {
  ...
  if (reference == frqReference) {
    /*
     * The client no longer has a reference to the
     * FinalizableReferenceQueue. We can stop.
     */
    throw new ShutDown();
  }

frqReference является PhantomReference на используемый ReferenceQueue, поэтому, если это GC, никакие Finalizable{Weak, Soft, Phantom}References не могут быть активными, поскольку они ссылаются на очередь.Таким образом, они должны быть GC'ed, прежде чем сама очередь может быть GC'ed - но тем не менее, получаем ли мы гарантию, что эти ссылки будут поставлены в очередь в очередь? ReferenceQueue в том порядке, в котором они «собирают мусор» (как если бы они собирали мусор один за другим)?В коде подразумевается, что есть какая-то гарантия, иначе необработанные ссылки теоретически могут остаться в очереди.

Спасибо

Это было полезно?

Решение

Гарантии на заказ нет.В случае Finalizer.java поток можно закрыть до того, как будут обработаны все ссылки.См. документацию FinalizableReferenceQueue:

  • Сохраняйте строгую ссылку на этот объект до тех пор, пока все связанные

  • референты были окончательно определены.Если этот объект представляет собой мусор, собранный ранее,
  • поддерживающий поток не будет вызывать {@code FinalizeReferent()} в
  • оставшиеся ссылки.

Это намеренное поведение.Например, мы используем FRQ для очистки записей карты, когда удаляются ссылки на ключи и/или значения.Если у пользователя больше нет ссылки на карту и, в свою очередь, больше нет ссылки на FRQ, нет смысла обрабатывать эти ссылки.

Другие советы

Я почти уверен, что ответ — нет.

Спецификация JVM говорит следующее о методах финализатора:

Виртуальная машина Java не накладывает никакого порядка на вызовы метода Finalize.Финализаторы могут вызываться в любом порядке или даже одновременно.(Спецификация JVM 2.17.7)

Из этого я делаю вывод, что нет никаких гарантий, что ссылки располагаются в очереди в топологическом порядке.

Я думаю, такой гарантии нет.Сам сборщик мусора не имеет полного и непосредственного представления об оперативной памяти (не может, поскольку сборщик мусора работает на процессоре, который может просматривать только несколько байтов за раз).В вашем примере, предполагая базовый сборщик мусора «пометка и очистка», есть вероятность, что A и B будут объявлены недостижимыми на одной и той же фазе пометки и будут сведены вместе в произвольном порядке.Поддержание топологического порядка, вероятно, будет дорогостоящим.

Что касается Finalizer, похоже, что он предназначен для использования через FinalizableReferenceQueue только экземпляр, который творит некоторую магию, связанную с загрузчиком классов.Тем Finalizer использует свои собственные средства для обнаружения, когда FinalizableReferenceQueue от которого оно функционально зависит, само становится недостижимым;это момент, когда поток, который работает Finalizer знает, что он должен выйти.Насколько я понимаю, если приложение позволяет GC вернуть FRQ, то поток финализатора завершится, и любые ссылки, поставленные в очередь «после» ссылки FRQ, не будут обработаны.Это зависит от топологического порядка или его отсутствия, но я не могу решить, проблема это или нет.Я думаю, что приложение не должно отказываться от своего FRQ, пока важна обработка возвращенных объектов, на которые ссылаются.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top