jdb : 在断点处执行预定义的操作
jdb : Perform a pre-defined action at a breakpoint
在使用 jdb 调试 java 应用程序时,是否可以使用预定义的操作设置断点。例如,如果我想知道当流经过某个点时某个变量的值是多少,我可以设置一个断点
> stop at MyClass:10
执行操作:
> print myVal
让程序继续。
> cont
基本上我想将以上三个命令合并/自动化为一个。
我知道我可以使用 expect 实现这一点,但我想要一些内置到 jdb 中的东西。
我的用例是能够在我无法附加常规 IDE 调试器或无法快速更改代码以添加日志的地方调试客户问题。
听起来您正在尝试将调试器用于并非真正用于某些用途的东西。
如果你有源代码,你描述的概念就可以解决。你可以只放一个 LOG4j 输出来实现你的目标。
我从未使用过 JDB 调试器,但我使用过许多不同的调试器。但是我做了一些研究,据我所知,我认为它不支持这种功能,这也是可以预期的。
我还没有看到执行类似操作的调试器。本质上你想要一个 "Watch feature" 但在类固醇上。即,您甚至不想单步执行程序流程本身。您希望在执行 java 操作码的特定行时执行一段代码。
要在机器级调试(而非 JVM)上实现类似的功能,您必须使用 codecaves/code 注入和迂回。所以你会拦截执行。此后您可以 modify/inspect 任何您想要更改的注册表。完成后,您将 return 到原始执行点。这是你通常出于恶意而做的事情:)。
最接近您当前目标的是条件断点,并将其与一些 Java 调试器提供的监视功能一起使用 - jdb 不提供。 Eclipse 和 Intellij 都支持条件断点和变量监视。
因此,只有当发生您感兴趣的事情时,您才可以在代码中设置断点。
我不知道有什么方法可以在 JDB 中完成此操作,但是,此功能存在于 IntelliJ IDEA 中。在断点属性中,您可以指定一个表达式,IDE 将计算它并记录结果,并且可以选择不停止地继续执行(如果您取消选中 "Suspend" 复选框)。
添加我自己的期望解决方案,以防其他人可能正在寻找这样的东西:
#!/usr/bin/expect --
set timeout -1
set DBGPROMPT "\\[1\\] "
set OPENBRACE "\\("
spawn ~/debug/jdk1.8.0_171/bin/jdb -attach 5005
# In case you had terminated on a suspended thread the last time
expect ">"
send -- "resume\r"
# add a breakpoint
expect ">"
send -- "stop in com.example.auth.MyClass.doStuff\r"
expect {
-regex "Breakpoint hit.*com.example.auth.MyClass.doStuff$OPENBRACE.*$DBGPROMPT"
{
send "print myVal\r"
exp_continue
}
-regex ".*tomcat-http.*$DBGPROMPT"
{
interact "3\[19~" return
send "cont\r"
exp_continue
}
}
interact
说明
该脚本为 class MyClass 的方法 doStuff 添加了一个断点。 expect 部分定义了两个动作。一个是我们设置的断点:打印 myVal 的值然后继续。第二个操作是您设置的任何断点的默认行为,您没有为其指定任何操作(甚至没有 continue )。当调试器在这样的断点处停止时,控制权将交给用户以他想要的方式与其交互。当他完成后,他可以按F8让程序继续。
如果要添加新的断点,复制粘贴注释 "add a breakpoint" 后的两行并将路径更改为 class / method。
您可以用类似的方式为行号添加断点。
我使用 'tomcat-http' 作为我的用例的正则表达式。如果需要,您可能需要更改此设置。
P.S。相应地更改 jdb 二进制文件的路径。
在使用 jdb 调试 java 应用程序时,是否可以使用预定义的操作设置断点。例如,如果我想知道当流经过某个点时某个变量的值是多少,我可以设置一个断点
> stop at MyClass:10
执行操作:
> print myVal
让程序继续。
> cont
基本上我想将以上三个命令合并/自动化为一个。
我知道我可以使用 expect 实现这一点,但我想要一些内置到 jdb 中的东西。 我的用例是能够在我无法附加常规 IDE 调试器或无法快速更改代码以添加日志的地方调试客户问题。
听起来您正在尝试将调试器用于并非真正用于某些用途的东西。
如果你有源代码,你描述的概念就可以解决。你可以只放一个 LOG4j 输出来实现你的目标。
我从未使用过 JDB 调试器,但我使用过许多不同的调试器。但是我做了一些研究,据我所知,我认为它不支持这种功能,这也是可以预期的。
我还没有看到执行类似操作的调试器。本质上你想要一个 "Watch feature" 但在类固醇上。即,您甚至不想单步执行程序流程本身。您希望在执行 java 操作码的特定行时执行一段代码。
要在机器级调试(而非 JVM)上实现类似的功能,您必须使用 codecaves/code 注入和迂回。所以你会拦截执行。此后您可以 modify/inspect 任何您想要更改的注册表。完成后,您将 return 到原始执行点。这是你通常出于恶意而做的事情:)。
最接近您当前目标的是条件断点,并将其与一些 Java 调试器提供的监视功能一起使用 - jdb 不提供。 Eclipse 和 Intellij 都支持条件断点和变量监视。
因此,只有当发生您感兴趣的事情时,您才可以在代码中设置断点。
我不知道有什么方法可以在 JDB 中完成此操作,但是,此功能存在于 IntelliJ IDEA 中。在断点属性中,您可以指定一个表达式,IDE 将计算它并记录结果,并且可以选择不停止地继续执行(如果您取消选中 "Suspend" 复选框)。
添加我自己的期望解决方案,以防其他人可能正在寻找这样的东西:
#!/usr/bin/expect --
set timeout -1
set DBGPROMPT "\\[1\\] "
set OPENBRACE "\\("
spawn ~/debug/jdk1.8.0_171/bin/jdb -attach 5005
# In case you had terminated on a suspended thread the last time
expect ">"
send -- "resume\r"
# add a breakpoint
expect ">"
send -- "stop in com.example.auth.MyClass.doStuff\r"
expect {
-regex "Breakpoint hit.*com.example.auth.MyClass.doStuff$OPENBRACE.*$DBGPROMPT"
{
send "print myVal\r"
exp_continue
}
-regex ".*tomcat-http.*$DBGPROMPT"
{
interact "3\[19~" return
send "cont\r"
exp_continue
}
}
interact
说明 该脚本为 class MyClass 的方法 doStuff 添加了一个断点。 expect 部分定义了两个动作。一个是我们设置的断点:打印 myVal 的值然后继续。第二个操作是您设置的任何断点的默认行为,您没有为其指定任何操作(甚至没有 continue )。当调试器在这样的断点处停止时,控制权将交给用户以他想要的方式与其交互。当他完成后,他可以按F8让程序继续。
如果要添加新的断点,复制粘贴注释 "add a breakpoint" 后的两行并将路径更改为 class / method。
您可以用类似的方式为行号添加断点。
我使用 'tomcat-http' 作为我的用例的正则表达式。如果需要,您可能需要更改此设置。
P.S。相应地更改 jdb 二进制文件的路径。