Отладка памяти и аннотации часов

Прежде чем погрузиться в отладку проблем с памятью и другие удивительные возможности запущенного процесса, отладки памяти (которые просто поражают воображение)… Я хочу обсудить один момент, который я оставил открытым в последнем посте про утят. Там мы обсуждали настройку рендеринга часов. Это супер круто!

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

Shai Almog
@debugagent
🦆 Утенок 10:
На этой неделе я продолжаю обсуждение пользовательских часов, сосредоточившись на расширенном представлении.
Затем я объясняю, как вы можете сделать это для всей вашей команды. Если вы являетесь пользователем Spring/JPA, это облегчит вам процесс отладки…
#CodeNewbie #140SecondDucklings
16:53 PM — 12 Apr 2022
Шай Альмог
@debugagent
🦆 Утёнок 11-й:
Знаете ли вы, что можно увидеть все объекты в памяти?
Вы можете сделать diff по объектам памяти между двумя точками останова или операцией step-over.
С буквальной трассировкой стека прямо к выделяющему коду!
#CodeNewbie #140SecondDucklings
19:20 PM — 19 Apr 2022

Аннотации часов

В прошлый раз мы обсуждали настройку пользовательского интерфейса часов для более эффективного рендеринга сложных объектов. Но с этим есть одна проблема: «Мы не одни».

Мы — часть команды. Делать это для каждой машины сложно и утомительно. А если вы создаете библиотеку или API и хотите, чтобы такое поведение было по умолчанию?

Именно здесь JetBrains предлагает уникальное решение: пользовательские аннотации. Просто аннотируйте свой код подсказками для отладчика, и конфигурация будет простой для всей вашей команды/пользователей. Для этого нам нужно добавить аннотации JetBrains в путь к проекту. Вы можете сделать это, добавив это в файл Maven POM:

<dependency>
 <groupId>org.jetbrains</groupId>
 <artifactId>annotations</artifactId>
 <version>23.0.0</version>
</dependency>
Войти в полноэкранный режим Выйти из полноэкранного режима

Как только это будет сделано, мы можем аннотировать класс из предыдущего утёнка для достижения того же эффекта

import org.jetbrains.annotations.Debug.Renderer;

// snipped code ...

@Renderer(text = ""Repository has " + count() + " elements",",
  childrenArray = "finaAll()",
  hasChildren = "count() > 0")
public interface VisitRepository extends JpaRepository<Visit, Integer> {
  // snipped code  ...
}
Войти в полноэкранный режим Выйти из полноэкранного режима

Обратите внимание, что нам нужно экранировать строки в аннотации, чтобы они были действительными строками Java. Нам нужно снять символы кавычек и использовать их для записи «правильной» строки.

Опять же, все остальное соответствует содержанию и результату, которые мы видели в предыдущем утёнке.

Отладчик памяти

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

Хуже. Это настолько влияет на производительность, что IntelliJ не загружает фактическое содержимое этого класса, пока мы явно не нажмем кнопку «Load Classes» в центре монитора памяти:

Как вы можете себе представить, это быстро надоедает. Если ваша машина медленная, то это замечательно. Но если у вас исключительно мощная машина, то, возможно, вы захотите включить функцию «Обновлять загруженные классы при остановке отладчика»:

Это эффективно отключает требование щелчка мыши ценой более медленного выполнения шага. Но что мы получаем в результате?

Использование памяти

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

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

Но это еще не все. Мы можем дважды щелкнуть на каждом объекте в списке и увидеть вот это:

Здесь мы видим все объекты данного типа, которые были выделены во всей куче. Мы можем получить представление о том, что действительно хранится в том или ином участке памяти, и снова получить более глубокое представление о потенциальных утечках памяти.

Проверки памяти

«Отслеживать новые экземпляры» позволяет еще больше отслеживать выделения кучи. Мы можем включить эту функцию для каждого типа объекта. Обратите внимание, что это относится только к «собственному объекту», но не к массивам. Вы можете включить его с помощью правого щелчка:

Как только мы включим эту функцию, выделения кучи будут отслеживаться везде. Мы получаем обратные следы выделения памяти, которые можно использовать для поиска точной строки кода, которая выделила каждый объект в куче!

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

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

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

Наконец

Одна из моих любимых вещей в Java — это отсутствие реальных ошибок памяти. Здесь нет недопустимых адресов памяти. Нет неинициализированной памяти, которая приводит к недопустимым обращениям к памяти. Нет недействительных указателей, нет адресов памяти (с которыми мы сталкиваемся) или ручной настройки. Все «просто работает».

Но все же есть болевые точки, которые выходят за рамки настройки сборки мусора. Размер кучи — одна из самых больших проблем в Java. Это не обязательно утечка. Иногда это просто расточительность, которую мы не понимаем. Куда девается лишняя память?

Отладчик позволяет нам провести прямую линию с трассировкой стека прямо к строке исходного кода. Мы можем исследовать содержимое памяти и получить применимую статистику памяти, что выходит далеко за рамки компетенции профилировщика. Для ясности: профилировщики отлично подходят для того, чтобы посмотреть на память в «общей картине». Отладчик может дополнить эту картину полным списком для конкретного блока кода.

Оцените статью
Procodings.ru
Добавить комментарий