Как дебажить java
Перейти к содержимому

Как дебажить java

  • автор:

Дебаг приложения на этапе компиляции IntelliJ IDEA

Рассказываю, как дебажить приложение на этапе компиляции с помощью intellij idea.

18 апр. 2021 · 2 минуты на чтение

Я столкнулся с необходимостью дебага annotation processor, когда писал библиотеку со своими аннотациями и обработчиками к ним. Проблема заключается в том, что обработка аннотаций происходит на этапе компиляции.

Спонсор поста

1. Создание Remote JVM Debug Configuration

Создаем новую конфигурацию. Вам нужно найти: “Remote JVM Debug”.

Выберите режим “Attach to remote JVM” и любой доступный порт, например 8000.

2. Убедитесь, что процесс сборки использует ваш порт

Нажмите Ctrl+Shift+A и найдите пункт “Edit Custom VM Options…”

Добавьте новую строку -Dcompiler.process.debug.port=8000 и перезапустите IDEA.

3. Включите “Debug build process”

Нажмите Ctrl+Shift+A и пункт “Debug build process”.

Вам нужно будет повторять этот шаг каждый раз при перезапуске IDEA.

4. Дебажим

Сначала установите точку останова в коде обработчика аннотаций.

Для запуска вашего обработчика аннотаций пересоберите проект: Build -> Rebuild Project. При выборе пункта Build Project обработчик аннотации может не запуститься.

Процесс сборки приостановится, и вы сможете подключить отладчик:

Теперь запустите добавленную вами конфигурацию в режиме Debug (Shift+F9). Javac возобновит компиляцию. IDEA теперь должна остановиться на установленной вами точке останова.

На этом все, теперь вы можете отлаживать ваши обработчики аннотаций.

Как в IntelliJ IDEA дебажить стримы Java 8?

Как в IntelliJ IDEA дебажить стримы Java 8? Все промежуточные вызовы ленивые и исполняются во время терминальной операции, так что, делать перенос методов на отдельные строки бессмысленно. Я пока не смог заставить идею показать элементы стрима на каком-то шаге, отличного от начального и конечного. System.out.println расставлять — как-то непрофессионально, есть другие способы из коробки?

Отслеживать

1,865 1 1 золотой знак 17 17 серебряных знаков 25 25 бронзовых знаков

задан 23 ноя 2016 в 15:07

695 3 3 серебряных знака 11 11 бронзовых знаков

Отладка Java-приложений из командной строки

Некоторые ошибки трудно воспроизвести на вашем персональном компьютере, но их легко воспроизвести на производственных или тестовых машинах. Это обычная ситуация, с которой часто сталкиваются профессиональные Java-разработчики. Для отладки таких проблем OpenJDK предоставляет два инструмента: remote debugging и jdb . Эта статья посвящена jdb .

Для приложений Java типичными производственными и тестовыми машинами являются серверы Linux без графического интерфейса, поэтому доступны только инструменты командной строки. И мы не можем использовать профессиональные IDE, такие как IntelliJ IDEA, Eclipse или Apache NetBeans IDE.

В таких сценариях мы можем использовать jdb . jdb — это отладчик командной строки, входящий в состав OpenJDK.

Это перевод руководства для начинающих. Очевидно эксперты все это знают и им не стоит тратит время на его чтение.

Отладка Java с помощью утилиты «jdb»

jdb расположена в каталоге jdk/bin. Она использует интерфейс отладки Java (JDI) для запуска и подключения к целевой JVM. Интерфейс отладки Java (JDI) предоставляет интерфейс языка программирования Java для отладки приложений на языке программирования Java. JDI является частью архитектуры отладчика платформы Java (Java Platform Debugger Architecture).

В этом разделе мы рассмотрим, как подключить jdb к java-приложению и начать отладку и мониторинг.

Команда jdb

Формат команды jdb:

jdb [options] [classname] [arguments] options: This represents the jdb command-line options (e.g. attach, launch). classname: This represents the name of the main class to debug. arguments: This represents the arguments that are passed to the main() method of the class.
Пример Java приложения для отладки

Ниже приведен пример Java класса, который мы собираемся отладить и попытаться понять различные доступные функции. Важно скомпилировать этот класс с параметром «-g» (javac -g Test.java), который генерирует всю отладочную информацию, включая локальные переменные. По умолчанию генерируется только информация о номере строки и исходном файле.

public class Test < public static void main(String[] args) < System.out.println("First Line of main function"); System.out.println("Second Line of main function"); System.out.println("Third Line of main function"); int i=0; System.out.println("i: " + i); i = 2; System.out.println("i: " + i); while(true) < >> >
Подключение jdb к java-приложению

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

jdb Test

Таким образом, мы запускаем выполнение основного класса «Test» аналогично тому, как мы запускаем выполнение основного класс в среде IDE. jdb останавливает JVM перед выполнением первой инструкции этого класса.

Другой способ использовать команду jdb для подключения ее к уже запущенной JVM. Синтаксис для запуска JVM с портом отладчика:

java -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:5005 Test

Чтобы подключить jdb к этому удаленному jvm, используйте синтаксис ниже:

jdb -attach 5005

В этой статье мы не будем подробно рассматривать удаленную отладку.

Отладка и мониторинг

Ниже приводится команда для присоединения jdb к Java-программе Test:

/jdk/bin/jdb Test Initializing jdb . >

Установите точку останова в строке 5, используя команду «stop», как показано ниже:

> stop at Test:5 Deferring breakpoint Test:5. It will be set after the class is loaded. >

Запустите выполнение основного класса приложения с помощью команды «run»:

> run run Test Set uncaught java.lang.Throwable Set deferred uncaught java.lang.Throwable > VM Started: Set deferred breakpoint Test:5 Breakpoint hit: "thread=main", Test.main(), line=5 bci=0 5 System.out.println("First Line of main function");

Выполнить текущую строку с помощью команды «step»:

main[1] step > First Line of main function Step completed: "thread=main", Test.main(), line=6 bci=8 6 System.out.println("Second Line of main function");

Выполнить текущую строку с помощью команды «step»:

main[1] step > Second Line of main function Step completed: "thread=main", Test.main(), line=7 bci=16 7 System.out.println("Third Line of main function");

Печать локальной переменной i с помощью команды «print»:

main[1] print i i = 0

Печать всех локальных переменных в текущем фрейме стека с использованием команды «locals»:

main[1] locals Method arguments: args = instance of java.lang.String[0] (id=841) Local variables: i = 0

Выгрузите стек потока, используя команду «where»:

main[1] where [1] Test.main (Test.java:10)

Выдать список потоков в запущенном приложении, используя команду «threads»:

main[1] threads Group system: (java.lang.ref.Reference$ReferenceHandler)804 Reference Handler running (java.lang.ref.Finalizer$FinalizerThread)805 Finalizer cond. waiting (java.lang.Thread)806 Signal Dispatcher running (java.lang.Thread)803 Notification Thread running Group main: (java.lang.Thread)1 main running Group InnocuousThreadGroup: (jdk.internal.misc.InnocuousThread)807 Common-Cleaner cond. waiting

Продолжить выполнение с точки останова, используя команду cont :

main[1] cont > i: 0 i: 2

Все доступные команды jdb можно получить используя команду «help»:

connectors -- list available connectors and transports in this VM run [class [args]] -- start execution of application's main class threads [threadgroup] -- list threads thread -- set default thread suspend [thread id(s)] -- suspend threads (default: all) resume [thread id(s)] -- resume threads (default: all) where [ | all] -- dump a thread's stack wherei [ | all]-- dump a thread's stack, with pc info up [n frames] -- move up a thread's stack down [n frames] -- move down a thread's stack kill -- kill a thread with the given exception object interrupt -- interrupt a thread print -- print value of expression dump -- print all object information eval -- evaluate expression (same as print) set = -- assign new value to field/variable/array element locals -- print all local variables in current stack frame classes -- list currently known classes class -- show details of named class methods -- list a class's methods fields -- list a class's fields threadgroups -- list threadgroups threadgroup -- set current threadgroup stop [go|thread] [] -- set a breakpoint -- if no options are given, the current list of breakpoints is printed -- if "go" is specified, immediately resume after stopping -- if "thread" is specified, only suspend the thread we stop in -- if neither "go" nor "thread" are specified, suspend all threads -- if an integer is specified, only stop in the specified thread -- "at" and "in" have the same meaning -- can either be a line number or a method: -- : -- .[(argument_type. )] clear .[(argument_type. )] -- clear a breakpoint in a method clear : -- clear a breakpoint at a line clear -- list breakpoints catch [uncaught|caught|all] | -- break when specified exception occurs ignore [uncaught|caught|all] | -- cancel 'catch' for the specified exception watch [access|all] . -- watch access/modifications to a field unwatch [access|all] . -- discontinue watching access/modifications to a field trace [go] methods [thread] -- trace method entries and exits. -- All threads are suspended unless 'go' is specified trace [go] method exit | exits [thread] -- trace the current method's exit, or all methods' exits -- All threads are suspended unless 'go' is specified untrace [methods] -- stop tracing method entrys and/or exits step -- execute current line step up -- execute until the current method returns to its caller stepi -- execute current instruction next -- step one line (step OVER calls) cont -- continue execution from breakpoint list [line number|method] -- print source code use (or sourcepath) [source file path] -- display or change the source path exclude [, . | "none"] -- do not report step or method events for specified classes classpath -- print classpath info from target VM monitor -- execute command each time the program stops monitor -- list monitors unmonitor -- delete a monitor read -- read and execute a command file lock -- print lock info for an object threadlocks [thread id] -- print lock info for a thread pop -- pop the stack through and including the current frame reenter -- same as pop, but current frame is reentered redefine -- redefine the code for a class disablegc -- prevent garbage collection of an object enablegc -- permit garbage collection of an object !! -- repeat last command -- repeat command n times # -- discard (no-op) help (or ?) -- list commands dbgtrace [flag] -- same as dbgtrace command line option version -- print version information exit (or quit) -- exit debugger : a full class name with package qualifiers : a class name with a leading or trailing wildcard ('*') : thread number as reported in the 'threads' command : a Java(TM) Programming Language expression.

Поддерживается весьма стандартный синтаксис команд.

Команды запуска могут быть помещены в файлы «jdb.ini» или «.jdbrc» в каталогах user.home или user.dir.

quit
Заключение

OpenJDK предоставляет множество замечательных инструментов для устранения неполадок и диагностики Java-приложений. Эти инструменты помогут вам быстро исправить проблемы в рабочем приложении. jdb может быть большим подспорьем, когда нет другого способа, кроме отладки приложения, а ваша любимая IDE недоступна. Знание таких функций поможет вам улучшить задание Java.

Чтобы помочь вам, автор статьи написал электронную книгу 5 steps to Best Java Jobs. Вы можете загрузить это пошаговое руководство бесплатно!

8 советов по отладке для пользователей IntelliJ IDEA, о существовании которых вы возможно не знали

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

Но давайте будем честными. Обычно мы используем только опцию точки останова. При большом желании мы можем использовать условную точку останова.

Но знаете что, отладчик IntelliJ IDEA имеет множество мощных и передовых функций, которые полезны для более эффективной и простой отладки.

Чтобы помочь вам, мы составили список советов и приемов от наших разработчиков в Lightrun. Мы надеемся, что эти советы помогут вам быстрее находить и устранять ошибки.

1. Используйте точки останова по исключениям

Точки останова — это места в коде, которые позволяют остановить программу и включить отладку. Они позволяют изучить поведение кода и его функции, чтобы попытаться определить ошибку.

Мы рекомендуем использовать точку останова по исключениям. Этот тип точки останова приостанавливает выполнение программы в соответствии с типом исключения, а не в заранее определенном месте. Мы особенно рекомендуем точку останова IntelliJ Exception, потому что вы также можете фильтровать класс или пакет, частью которого являются исключения.

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

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

Lightrun предлагает моментальные снимки — точки останова, которые не останавливают работу программы. Узнайте больше здесь.

2. Используйте условия в ваших точках останова

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

В приведенном ниже цикле вы можете видеть, что точка останова остановит сервис, когда значение идентификатора агента равно нулю. Таким образом, вместо того, чтобы генерировать исключение с null указателем, мы сможем проверить текущее состояние VM (виртуальной машины) до того, как это произойдет.

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

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

3. Включите меню «Internal Actions» для разработки собственных плагинов.

Если вы пишете собственный плагин IntelliJ IDEA, включите внутренние действия (Tools -> Internal Actions) для упрощения отладки. Эта функция включает в себя множество удобных опций, таких как инспектор компонентов и отладчик пользовательского интерфейса. Всегда удобно иметь в своем распоряжении широкий набор инструментов, предоставляющих вам возможности, о которых вы, возможно, никогда не думали.

Чтобы включить внутренние действия, выберите «Help -> Edit Custom Properties». Затем введите idea.is.internal=true и сохраните. После перезапуска вы должны увидеть новую опцию в меню «Tools».

4. Используйте функцию «Analyze Thread Dump».

Дамп потока — это моментальный снимок, который показывает, что каждый поток делает в определенное время. Дампы потоков используются для диагностики системы и проблем с производительностью. Анализ дампов потоков позволит вам выявить тупиковые ситуации или проблемы конкуренции.

Мы рекомендуем использовать функцию IntelliJ «Analyze Thread Dump» из-за ее удобных возможностей просмотра, которые упрощают анализ дампа. «Analyze Thread Dump» автоматически обнаруживает трассировку стека в буфере обмена и мгновенно помещает ее со ссылками на исходный код. Эта возможность очень полезна при просмотре дампов стека из журналов сервера, потому что вы можете мгновенно перейти к соответствующим файлам, как при локальной трассировке стека.

Чтобы получить доступ к функции, перейдите в меню «Analyze». IDE поддерживает активацию этой функции динамически, когда IDE обнаруживает трассировку стека в буфере обмена.

5. Используйте отладчик потока.

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

В IntelliJ появился новый классный инструмент — Stream Debugger. Вы можете использовать его для визуальной проверки результатов потоковой операции. При достижении точки останова в потоке нажмите значок отладчика потока в отладчике. Вы увидите отображение пользовательского интерфейса значения элементов потока на каждом этапе/функции потока. Таким образом, визуализируется каждый шаг, и вы можете видеть операции в потоке и обнаруживать проблему.

6. Используйте точку наблюдения за полем (Field Watchpoints)

Точка наблюдения за полем — это точка останова, приостанавливающая выполнение программы при доступе к заданному полю или его изменении.

Она может быть очень полезно, когда вы исследуете и обнаруживаете, что поле имеет неправильное значение, и вы не знаете, почему. Наблюдение за этим полем может помочь определить причину неисправности.

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

7. Отладка микросервисов с помощью подключаемого модуля Lightrun.

Плагин Lightrun IntelliJ позволяет добавлять журналы, снимки состояния и показатели производительности во время работы сервиса. Это означает, что вы можете добавлять инструменты в производственную и промежуточную среды. Вы можете отлаживать монолитные микросервисы, Kubernetes, K8, Docker Swarm, ECS, Big Data Workers, бессерверную систему и многое другое. Поддержка нескольких экземпляров доступна через механизм тегов.

Плагин Lightrun полезен для экономии времени, поэтому вместо многократных итераций локального воспроизведения сред, перезапусков и повторных развертываний вы можете выполнять отладку прямо в производственной среде.

8. Используйте друга — реального или воображаемого.

Когда дело доходит до мозгового штурма, 1 + 1 = 3. А когда дело доходит до решения сложных проблем отладки, вам понадобятся все умственные способности, которые вы можете использовать.

Работа с кем-то позволяет по-новому взглянуть на проблему по-другому и может выявить детали, которые вы упустили.

Или вы оба дополняете друг друга, пока не достигнете решения. Просто задавая друг другу вопросы и опровергая некоторые предположения друг друга, вы придете к новым выводам, которые помогут вам найти проблемы.

Вы также можете использовать друг друга для «Rubber Duck Debugging», или, как мы любим это называть, «Cheetah debugging».

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

Вы можете найти список онлайн сообществ разработчиков Java здесь.

Как мы уже упоминали в подсказке № 7, плагин Lightrun IntelliJ позволяет разработчикам отлаживать живые микросервисы, не прерывая их. Вы можете безопасно добавлять журналы и показатели производительности в производственную и промежуточную среду в режиме реального времени по запросу. Запросите демонстрацию и узнайте больше.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *