Отладка 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 [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), который генерирует всю отладочную информацию, включая локальные переменные. По умолчанию генерируется только информация о номере строки и исходном файле.
Подключение jdb к java-приложению
Приведенная ниже команда — это наиболее распространенный способ запуска приложения с отладчиком jdb. Здесь мы не передаем никаких параметров jdb, мы передали только имя класса, который не требует никаких аргументов:
Таким образом, мы запускаем выполнение основного класса «Test» аналогично тому, как мы запускаем выполнение основного класс в среде IDE. jdb останавливает JVM перед выполнением первой инструкции этого класса.
Другой способ использовать команду jdb для подключения ее к уже запущенной JVM. Синтаксис для запуска JVM с портом отладчика:
java -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:5005 Test
Чтобы подключить jdb к этому удаленному jvm, используйте синтаксис ниже:
В этой статье мы не будем подробно рассматривать удаленную отладку.
Отладка и мониторинг
Ниже приводится команда для присоединения 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»:
Печать всех локальных переменных в текущем фрейме стека с использованием команды «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 :
Все доступные команды 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.
Заключение
OpenJDK предоставляет множество замечательных инструментов для устранения неполадок и диагностики Java-приложений. Эти инструменты помогут вам быстро исправить проблемы в рабочем приложении. jdb может быть большим подспорьем, когда нет другого способа, кроме отладки приложения, а ваша любимая IDE недоступна. Знание таких функций поможет вам улучшить задание Java.
Чтобы помочь вам, автор статьи написал электронную книгу 5 steps to Best Java Jobs. Вы можете загрузить это пошаговое руководство бесплатно!