Невозможные ссылки на память Java в дамп кучи - PullRequest
4 голосов
/ 13 января 2011

У меня есть дамп кучи Java, взятый в 19:41, который я анализирую с помощью Eclipse Memory Analysis Tool. Дамп кучи включает 20 объектов сеанса.

Использование команды Path to GC Roots для одного из этих объектов сеанса в моей куче показывает следующие 3 ссылки на объект сеанса.

  • Ссылка на финализатор из "нефинализированного" связанного списка, принадлежащего потоку Финализатора. Мой объект занимает 3-е место в очереди для завершения.
  • Сильная ссылка на объект сеанса из потока обработчика сообщений, на который сама ссылается очистка TimerTask, запланированная на выполнение в 7:11 вечера.
  • Слабая ссылка на объект сеанса из записи WeakHashMap $ Entry. WeakHashMap поддерживается статической сильной ссылкой.

Как объект сеанса может находиться в очереди финализатора, когда он все еще имеет сильную и слабую ссылку?

Из оставшихся 19 объектов сеанса еще 1 находится в очереди финализатора и имеет аналогичную слабую ссылку. Все остальные 18 объектов сеанса имеют слабую ссылку. Почему GC не очистил эти слабые рефери?

Несколько общих замечаний:

  • Объекты подлежат финализации только ПОСЛЕ того, как их слабые ссылки были очищены (http://download.oracle.com/javase/6/docs/api/java/lang/ref/package-summary.html)
  • У объекта сеанса нет финализатора, который мог бы воскресить его, и даже если бы он это сделал, он не мог быть запущен, пока объект находится в незавершенной очереди позади других объектов.
  • Мое приложение не использует ссылки Phantom, которые являются единственными ссылками, которые должны существовать после того, как объект может быть завершен. Даже если мое приложение использовало фантомные ссылки, эти объекты не отображают свою ссылку на объект, который они содержат.

Ответы [ 3 ]

10 голосов
/ 21 января 2011

Я думаю, что ошибка, которую вы делаете здесь, заключается в этой части:

Ссылка финализатора из "нефинализированного" связанного списка, принадлежащего потоку Финализатора.Мой объект занимает 3-е место в очереди для завершения.

Если вы говорите об этом:

static private Finalizer unfinalized = null;

в ВС Finalizer.java (Finalizer содержит next и prev Finalizer, следовательно, часть «связанный список», для тех, кто играет дома), тогда это не список вещей, которые должны быть завершены.

Finalizer.add() нет (как ядумаю, что вы предполагаете) вызывается во время процесса завершения, когда объект недоступен;скорее, этот метод вызывается во время создания объекта (например, в течение <init>, по собственному коду для любого объекта, который переопределяет finalize().

Наличие финализатора вцепочка next не означает, что она должна быть завершена, это

static private ReferenceQueue queue

, которая содержит такие объекты. Наличие в связанном списке просто означает, что имеет *1029* a finalize() method.

Следовательно, ваша первая точка - красная сельдь, ваша вторая точка обеспечивает доступ к элементу, а третья точка вытекает из второй (потому что WeakReference не будет очищен, пока объектдостижимо).

Надеюсь, это поможет!

0 голосов
/ 23 января 2011

Вы можете сделать объект, запланированный для финализации, снова доступным.

Я знаю о:

Объект сеанса не иметь финализатор, который мог бы воскресить его, и даже если он это сделал не мог быть запущен в то время как объект все еще находится в незавершенном очередь за другими объектами.

Однако могут быть и другие объекты, которые делают это (то есть имеют ссылку на сессию и получают сами себя). В любом случае покажите финализатор этой сессии.

примечания: перед очисткой фантомных ссылок Объект НЕ будет доступен для завершения. (Призрачные ссылки чаще всего используются для планирования pre-mortem действий по очистке, javadoc ), pre (не публиковать, как слабые).

0 голосов
/ 13 января 2011

Слабые ссылки являются лишь указанием на ГХ.У вас нет твердых гарантий, когда он будет очищен.

...