Понимание дампа кучи Java - PullRequest
3 голосов
/ 20 июля 2011

Я пытаюсь найти утечку памяти в приложении уже неделю, но безуспешно. Я попытался сделать дамп кучи и использовать jhat, чтобы посмотреть на дамп и отследить утечку памяти.

Это лучший подход? Какой лучший способ отследить утечку памяти с помощью дампа кучи.

Ценю вашу помощь.

Используемая виртуальная машина: Java-версия "1.6.0_25" Java (TM) SE Runtime Environment (сборка 1.6.0_25-b06) Java HotSpot (TM) 64-разрядная серверная виртуальная машина (сборка 20.0-b11, смешанный режим)

Параметры JVM: -Xmx1600m -XX: + UseParallelGC -XX: MaxPermSize = 256m -Xms1600m -XX: + HeapDumpOnOutOfMemoryError -XX: + PrintGCDetails -XX: + PrintGCTloggcta: -g: TMP / gc.log

OOME Stack trace: Не удалось получить это. Ядро убило процесс с ошибкой нехватки памяти.

GC Log: Последние несколько строк

48587.245: [GC [PSYoungGen: 407168K->37504K(476160K)] 506729K->137065K(1568448K), 3.0673560 secs] [Times: user=3.53 sys=0.00, real=3.07 secs] 
50318.617: [GC [PSYoungGen: 444224K->37536K(476416K)] 543785K->175177K(1568704K), 3.6635990 secs] [Times: user=3.70 sys=0.00, real=3.67 secs] 
50453.841: [GC [PSYoungGen: 70092K->2912K(476672K)] 207734K->178513K(1568960K), 1.0164250 secs] [Times: user=1.29 sys=0.00, real=1.02 secs] 
50454.858: [Full GC (System) [PSYoungGen: 2912K->0K(476672K)] [PSOldGen: 175601K->137776K(1092288K)] 178513K->137776K(1568960K) [PSPermGen: 60627K->60627K(74368K)], 2.0082140 secs] [Times: user=2.09 sys=0.00, real=2.01 secs] 
52186.496: [GC [PSYoungGen: 407104K->37312K(444416K)] 544880K->175088K(1536704K), 3.3705440 secs] [Times: user=3.93 sys=0.00, real=3.37 secs] 
53919.975: [GC [PSYoungGen: 444416K->37536K(476608K)] 582192K->213032K(1568896K), 3.4242980 secs] [Times: user=4.09 sys=0.00, real=3.42 secs] 
54056.872: [GC [PSYoungGen: 70113K->2880K(476480K)] 245609K->216320K(1568768K), 0.9691980 secs] [Times: user=1.19 sys=0.00, real=0.97 secs] 
54057.842: [Full GC (System) [PSYoungGen: 2880K->0K(476480K)] [PSOldGen: 213440K->99561K(1092288K)] 216320K->99561K(1568768K) [PSPermGen: 60628K->60628K(72320K)], 2.2203320 secs] [Times: user=2.23 sys=0.01, real=2.22 secs] 
55796.688: [GC [PSYoungGen: 406976K->37504K(476160K)] 506537K->137065K(1568448K), 3.2680080 secs]

Обновление: После проверки сообщений в журнале ядра, он является oom-killer. Но все же, почему система убивает процесс, не потому ли, что процесс поглощает много системных ресурсов (памяти).

Ответы [ 3 ]

8 голосов
/ 20 июля 2011

Вопрос об утечках памяти в Java является дубликатом этого , , и т. Д. Тем не менее, вот несколько мыслей:

Начните с несколькихснимки кучи, как описано в ответе, связанном выше.

Затем, если вы хорошо знаете все приложение, вы можете просмотреть количество экземпляров и найти, какой тип имеет слишком много экземпляров.Например, если вы знаете, что класс является одноэлементным, но вы видите в памяти 100 экземпляров этого класса, то это верный признак того, что там происходит что-то смешное.В качестве альтернативы вы можете сравнить снимки, чтобы определить, какие типы объектов растут с течением времени;ключ здесь в том, что вы ищете относительный рост в течение некоторого периода использования.

Как только вы узнаете, что происходит, вы проследите по ссылкам, чтобы найти корневую ссылку, которая не может быть собрана.

Наконец, помните, что возможно, что вы видите ошибку OutOfMemoryError не потому, что у вас происходит утечка памяти, а скорее потому, что некоторая часть вашей кучи слишком мала для приложения.Чтобы проверить, так ли это:

  • Включите в свой вопрос тип используемой виртуальной машины.
  • Включите в свой вопрос аргументы, которые вы передаете при запуске Java.Каковы ваши размеры min, max и permgen heap?Какой тип сборщика мусора вы используете?
  • Включите в свой вопрос трассировку стека OOME, если там есть какая-то полезная информация.
  • Включите подробное ведение журнала GC, чтобы вы могли увидеть, какиечасти (и) кучи растут.
  • Включите параметр HeapDumpOnOutOfMemoryError , чтобы получить дамп кучи в самом конце, когда процесс умирает.

Обновление : Я не уверен, что означает, что «ядро завершило процесс с ошибкой нехватки памяти» в вашем последнем обновлении означает, но я думаю, вы могли бы сказать, что Linux не хватает памятиубийца был вызван.Это был случай?Эта проблема полностью отделена от ошибки Java OutOfMemoryError.Подробнее о происходящем можно узнать по ссылкам со страницы, на которую я только что ссылался, включая this и that .Но решение вашей проблемы простое: используйте меньше памяти на рассматриваемом сервере.Я предполагаю, что вы можете сбросить минимальный и максимальный размер кучи рассматриваемого Java-процесса, но вы должны быть уверены, что не вызовете реальные java-ошибки OutOfMemoryErrors.Можете ли вы перенести некоторые процессы в другое место?Можете ли вы соотнести убийцу памяти с запуском определенного процесса?

1 голос
/ 26 марта 2018

Утечки памяти можно устранить, выполнив следующие 3 простых шага:

Шаг 1: Захват дампа кучи на ранней стадии

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

   jmap -dump:format=b,file=<file-path> <pid> 

   where

   pid: is the Java Process Id, whose heap dump should be captured
   file-path: is the file path where heap dump will be written in to.

Если вы не хотите использовать jmap для захвата дампов кучи, вот несколько других вариантов захвата дампов кучи .

Шаг 2: Захват дампа кучи до сбоя приложения

После выполнения шага 1, позвольте приложению работать. Перед сбоем приложения сделайте еще один дамп кучи еще раз. Часто бывает сложно собрать дамп кучи до его сбоя, потому что мы не знаем, когда произойдет сбой приложения. Это через 30 минут, 3 часа, 3 дня? Таким образом, лучше всего запускать ваше приложение со следующим свойством JVM:

    -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=<file-path>

    file-path: is the file path where heap dump will be written in to.

Это свойство будет запускать дамп кучи прямо при возникновении OutOfMemoryError.

Шаг 3: Анализ дампов кучи

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

Вы можете использовать для этой цели инструмент для анализа дампа кучи, например HeapHero.io , Eclipse MAT . Когда вы загружаете дампы кучи в любой из инструментов, появляется раздел, сообщающий о самых больших объектах в памяти. Сравните этот раздел между дампом кучи, записанным на шаге 1 и шагом 2. Если вы заметили какой-либо ненормальный рост объектов, то именно они вызывают утечку памяти в вашем приложении.

0 голосов
/ 26 августа 2013

Я рекомендую вам просмотреть мою оригинальную статью на эту тему.Сначала анализ дампа кучи Java может быть сложным, но использование таких инструментов, как Eclipse Memory Analyzer , упрощает процесс.

Дамп кучи JVM полезен для следующих сценариев:

  • Идентификация утечки памяти на уровне Java.
  • Идентификация утечки загрузчика классов на уровне Java.
  • Чтобы узнать больше об объеме памяти вашего приложения Java при определенном сценарии загрузки / трафика.

Ссылка: Дамп кучи Java: готовы ли вы к задаче?

...