Отслеживание исключений OOM

Java

  • Продукт: Ding (отправлен execl), это данные, которые нужно очистить сегодня.
  • Я: А? ? ? ? какова ситуация? ? ?
  • Продукт: ранее было добавлено новое поле, и необходимо дополнить исторические данные
  • я: я разрабатываю требования
  • Продукт: Хорошо, сегодня закончил
  • я:........я умываюсь!

Итак, после того, как я сегодня написал программу очистки данных, я попросил брата по эксплуатации и обслуживанию запустить ее.В процессе очистки произошла ошибка.OOMненормальная ситуация. Затем пусть брат по эксплуатации и обслуживанию поместит соответствующую информацию о стеке потока и информацию о памяти.dumpвниз.

сначала объясниOOMВозможные причины:

  • outOfMemoryError Старого поколения не хватает памяти.
  • outOfMemoryError: PermGen Space не хватает памяти в постоянном поколении.
  • outOfMemoryError: Превышен лимит накладных расходов сборщика мусора Время сборки мусора занимает 98% или более времени работы системы.

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

дисплей проблемы

журнальный файл:

时间戳 [http-nio-端口号-exec-1] ERROR ResponseExceptionHandle:26 - Handler dispatch failed; nested exception is java.lang.OutOfMemoryError: GC overhead limit exceeded
org.springframework.web.util.NestedServletException: Handler dispatch failed; nested exception is java.lang.OutOfMemoryError: GC overhead limit exceeded
	****中间一大段****
Caused by: java.lang.OutOfMemoryError: GC overhead limit exceeded

В это время было бы неплохо иметь визуальный интерфейс (или иметь компьютер для работы и обслуживания, используйте его самостоятельноArthasПоднимитесь 😂), нет возможности, можно загрузить только информацию о стеке потока операций и обслуживания и информацию о памяти.

команда makefile в линукс

# 生成堆转储快照dump文件命令
jmap -dump:format=b,file=heapdump.hprof pid
# 生成线程堆栈信息文件命令
jstack -l pid >> stack.txt

Просмотр информации о стеке

"http-nio-端口号-exec-1" #37 daemon prio=5 os_prio=0 tid=0x00007f789d236800 nid=0x650e waiting on condition [0x00007f7851409000]
   java.lang.Thread.State: WAITING (parking)
	at sun.misc.Unsafe.park(Native Method)
	- parking to wait for  <0x00000000faa51ba0> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
	at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)
	at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2039)
	at java.util.concurrent.LinkedBlockingQueue.take(LinkedBlockingQueue.java:442)
	at org.apache.tomcat.util.threads.TaskQueue.take(TaskQueue.java:103)
	at org.apache.tomcat.util.threads.TaskQueue.take(TaskQueue.java:31)
	at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1067)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1127)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
	at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
	at java.lang.Thread.run(Thread.java:745)

   Locked ownable synchronizers:
	- None
****等等容器内其他线程

Вышеупомянутое является просто просмотром состояния потока контейнера, который я перехватил всю информацию о стеке потока.Весь файл не найден.死锁происходит, нет проблем с потоком, и не будет ни одного потока, конкурирующего за ресурсы, что приведет к блокировке внутреннего запроса службы.OOMвозникает ситуация.

Просмотр снимка сброса кучи

Мы используем приведенную выше команду для вывода кучи Java в двоичном формате hprof в файл с указанным именем. Открыть его как обычный файл точно не получится (о чем вы думаете? Просыпайтесь). У меня есть два способа обработки и анализа файлов такого типа.

1. Использоватьjhat

использоватьJDKВ нем инструкции по анализу файла (иногда сбрасываемая куча бывает очень большой, и при запуске будет сообщать об ошибке недостаточного места в куче, и можно добавить параметры:jhat -J-Xmx512m <heap dump file>. Этот объем памяти может быть установлен в соответствии с вашим компьютером. ):

Затем вы можете ввести в браузереhttp://localhost:7000/Чтобы получить доступ:

Текущая страница показывает классы и идентификаторы, содержащиеся в текущем контейнере. Внизу страницы находится панель навигации:

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

Как правило, исключения кучи в основном просматриваются в этих двух частях:

  • Показать количество экземпляров для всех классов (кроме платформы), всю информацию об объектах вне платформы. Как показано ниже:
  • Показать гистограмму кучи, отображающую состояние кучи в виде древовидной диаграммы. Как показано ниже:

Следует отметить, что анализ, как правило, не выполняется непосредственно на сервере, так как это трудоемкий и аппаратно-ресурсоемкий процесс.Как правило, файл дампа, созданный сервером, копируется на локальную или другую машину для анализа.

2. ИспользоватьMemory Analyzer

Открытьmat(Установите MAT на стороне MAC), а затем импортируйте файл:

Здесь очень много параметров (еще не все прочитал 😂):

Shallow Heap представляет собой общий объем памяти, потребляемый объектом. Сохраненный набор объекта X относится к набору объектов, которые будут утилизированы сборщиком мусора после того, как X будет удален сборщиком мусора. Сохраненная куча объекта X относится к сумме неглубокой кучи всех объектов в сохраненном наборе X или к размеру памяти, которая остается активной из-за объекта X.

Смотрим варианты ниже:

  1. Гистограмма может отображать количество объектов в памяти, количество объектов и размер.
  2. Dominator Tree может перечислить этот поток и пространство, занимаемое этими объектами под потоком.
  3. Лучшие потребители перечисляют самые большие объекты графически.
  4. Leak Suspects автоматически анализирует причину утечек через MA.

Мы видим самую большую область (занимает 41 МБ): мы видим, что нижний левый угол — это имя экранного объекта:org.hibernate.internal.SessionFactoryImpl. Наша структура слоя сохраняемости технического стека используетhibernate(Но не очень понимание базового 😂).

мы нажимаемLeak Suspects, затем появляется:

проходить черезMATВозникли две предполагаемые проблемы, связанные с утечкой памяти:

Мы знаем, глядя на описание проблемы ниже:

Вопрос 1: БылLaunchedURLClassLoaderТот, который загружается загрузчиком классовSessionFactoryImplв случаеBoundedConcurrentHashMapНакопленный объем памяти, занимающий 42 984 656 байт.

Вопрос 2: естьSystemClassLoader7941 загруженоClassобъект, занимающий 10 075 768 байт.

Начните с Q1, чтобы просмотреть:

  1. Описание Описание
  2. Кратчайшие пути к точке накопления
  3. Накопленные объекты по классу в доминирующем дереве
  4. Все накопленные объекты по классам

Здесь мы выбираем просмотр проблемы накопления памяти внутри текущего контейнера из следующих трех. Второй выше — проследить от точки накопления до потока, и вы можете видеть, что каждый поток соответствуетShallow Heapтак же какRetained heap.

Паодин Цзе Нючжун

Мы видим здесь третий:

Мы смотрим на этоSessionFactoryImplсерединаQueryPlanCacheСуществует коллекция карт в , которая занимает много места в памяти. Этот класс не использовался в реальном приложении, но, глядя на это приглашение и имя, я лично чувствую, что он похож наConcurrentHashMapПохожие 😂 (Правильно большие парниBoundedConcurrentHashMapЯ понимаю, вы можете прокомментировать, чтобы позволить мне расширить свои знания). пройти черезQueryPlanCacheВы можете знать, что он используется для кэширования планов запросов, то есть для кэширования операторов SQL, чтобы один и тот же SQL можно было многократно компилировать.

Данные, которые я очистил на этот раз, составляют около 40 Вт, и каждый параметр отличается, поэтому это может привести кhibernateПри запросе кешировать большое количествоsqlПривести кheapПереполнение памяти (до сих пор мало что знаю о нашем стеке технологий... стыдно-стыдно), если вы знаете проблему, вы должны найти способ ее решить~~~

Наконец-то проголосуйте 😂2019 год новичка в области бэкенда | Ежегодный очерк Nuggets