JDB -- 如何在运行程序之前获取方法列表?

发布于 2024-09-10 15:37:03 字数 340 浏览 7 评论 0 原文

我正在学习 JDB 并遇到了一些悖论。启动 JDB(使用“jdb ClassName”)后,大多数教程会告诉我输入

>方法类名

查看可用方法的列表,以便我可以设置断点。如果我这样做,JDB 会回复

在使用“run”命令启动虚拟机之前,命令“methods”无效

当然,如果我在设置任何断点之前说“run”,它会直接运行;不是很有帮助。我唯一能得出的结论是 jdb 希望您盲目地设置断点,但这似乎是一个严重的疏忽,我坚持认为我只是错过了一个命令。

非常感谢! 乔伊斯

I'm learning JDB and running into a bit of a paradox. After starting JDB (with "jdb ClassName") most tutorials will tell me to type

> methods ClassName

to see a list of available methods so that I can set my breakpoints. If I do that, JDB replies

Command 'methods' is not valid until the VM is started with the 'run' command

Of course, if I say "run" before setting any breakpoints, it runs straight through; not very helpful. The only thing I can conclude is that jdb expects you to set your breakpoints blind, but this seems like such a gross oversight, I'm holding out that I'm simply missing a command.

Many thanks!!
Joyce

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

生寂 2024-09-17 15:37:03

请注意,有两种方法可以创建调试会话(请参阅jdb 文档)。

  1. 附加 - 我们将程序加载到虚拟机中,它暂停侦听端口(例如 8000)。然后在另一个终端会话中,我们加载 jdb 并通过指定端口将其附加到 JVM 会话。
    • 在一个终端会话中:java -Xdebug -agentlib:jdwp=transport=dt_socket,
      地址=8000,服务器=y,挂起=y类名
    • 在第二个终端会话中:jdb -attach 8000
  2. 启动 - 加载 jdb 并告诉它的名称要加载的类。
    • 在单个终端会话中:jdb ClassName

如果您要附加,则无需使用 run 命令。
但是,如果您启动,那么您确实需要使用run命令(虚拟机尚未启动)。


此行为可以从 man jdb 推断出来:

运行 -
启动 jdb 并设置任何必要的断点后,使用此
命令开始执行被调试的应用程序。 这个
仅当 jdb 启动调试应用程序时命令才可用
(而不是附加到现有虚拟机)

这就是您收到错误消息的原因。您启动了调试器,但没有使用运行命令
有些教程可能会错误地告诉您启动 jdb,但忘记告诉您执行run 命令。


下面展示了如何获取方法列表(假设您在名为 ClassName 的类中有 main 方法)。

  1. 正在附加
    jdb -attach 8000
    main[1]停在ClassName.main
    主要[1]续
    main[1] 方法 ClassName

  2. 启动
    jdb 类名
    <代码>>停在ClassName.main
    <代码>>运行
    main[1] 方法 ClassName

提示:查看jdb的命令提示符。有时它是>,有时它就像main[1]。如果是 >,则虚拟机尚未启动,并且 classesmethods 等命令将无法工作,直到您使用 <代码>运行命令。如果提示符为 main[1],则虚拟机已启动并且所需的命令将起作用。


我唯一能得出的结论是jdb希望你盲目设置断点

单独使用调试器很难设置断点。您需要在其他地方查看源代码。您可能会知道至少一种要中断的方法的名称,从而使用以下命令设置初始断点
停在ClassName.MethodName。如果您不知道在哪里断点,可以随时使用 stop in ClassName.Main 在 main 方法上设置断点。
请记住,当调试器运行时,您可以设置更多断点。此外,您可能会发现 list 命令很有用 - 它显示与当前断点命中相对应的源代码。

Note that there are two ways to create a debugging session (see the jdb documentation).

  1. Attaching - We load the program into a virtual machine, it pauses listening on a port (e.g. 8000). Then in another terminal session, we load jdb and attach it to the JVM session by specifying the port.
    • in one termial session:java -Xdebug -agentlib:jdwp=transport=dt_socket,
      address=8000,server=y,suspend=y ClassName
    • in a second terminal session: jdb -attach 8000
  2. Launching - Load jdb and tell it the name of the class to load.
    • in a single terminal session: jdb ClassName

If you are attaching, then you don't need to use the run command.
However, if you are launching, then you do need to use the run command (the virtual machine hasn't been started yet).


This behaviour can be inferred from man jdb:

run -
After starting jdb, and setting any necessary breakpoints, use this
command to start the execution of the debugged application. This
command is available only when jdb launches the debugged application
(as opposed to attaching to an existing VM)
.

This is why you have the error message. You launched the debugger but didn't use the run command.
Some tutorials may incorrectly tell you to launch jdb, but forget to tell you to execute the run command.


Below shows how to get the list of methods (assuming you have main method in a class called ClassName).

  1. Attaching:
    jdb -attach 8000
    main[1] stop in ClassName.main
    main[1] cont
    main[1] methods ClassName

  2. Launching:
    jdb ClassName
    > stop in ClassName.main
    > run
    main[1] methods ClassName

Hint: look at jdb's command prompt. Sometimes it's >, sometimes it's like main[1]. If it's >, then the VM hasn't started and commands such as classes, methods won't work until you have used the run command. If the prompt is main[1], the VM has been started and desired commands will work.


The only thing I can conclude is that jdb expects you to set your breakpoints blind

It is difficult to set breakboints using the debugger alone. You need to be looking at your source code elsewhere. You will likely know the name of at least one method to break at and thus set an initial breakpoint using
stop in ClassName.MethodName. If you don't know where to break, you can always set a breakpoint on your main method using stop in ClassName.Main.
Remember that while the debugger is running, you can set more breakpoints. Also, you may find, the list command useful - it shows the source code corresponding to the current breakpoint hit.

羁拥 2024-09-17 15:37:03

我也有同样的问题。

因此,运行后:

jdb -classpath build -sourcepath src MyClass

我输入的文本在 jdb 会话中以粗体显示:

> stop in MyClass.main
Deferring breakpoint MyClass.main.
It will be set after the class is loaded.
> run
run MyClass
Set uncaught java.lang.Throwable
Set deferred uncaught java.lang.Throwable
> 
VM Started: Set deferred breakpoint MyClass.main

Breakpoint hit: "thread=main", MyClass.main(), line=798 bci=0
798         MyClass singleton = new MyClass();

main[1] list
797     public static void main(String[] args) {
798 =>      MyClass singleton = new MyClass();
799         

I had exactly the same question.

So after running:

jdb -classpath build -sourcepath src MyClass

the text I entered is in bold below in the jdb session:

> stop in MyClass.main
Deferring breakpoint MyClass.main.
It will be set after the class is loaded.
> run
run MyClass
Set uncaught java.lang.Throwable
Set deferred uncaught java.lang.Throwable
> 
VM Started: Set deferred breakpoint MyClass.main

Breakpoint hit: "thread=main", MyClass.main(), line=798 bci=0
798         MyClass singleton = new MyClass();

main[1] list
797     public static void main(String[] args) {
798 =>      MyClass singleton = new MyClass();
799         
〃安静 2024-09-17 15:37:03

如果您正在调试的是您自己的程序,我想您会知道类名!

如果您没有源代码,那么要运行它,您必须知道包含 main() 的类名。如果它位于以 java -jar 开头的 jar 中,则该类的名称位于 jar 内的清单中。

但实际上您正在运行jdb ClassName,因此您知道您将运行方法ClassName.main()。正确的?

如果它是 Web 服务中的 Servlet,则该 Servlet 的类位于 web.xml 中。

因此,在任何这些情况下,您至少应该能够获得第一个方法。一旦到达那里,您就可以找到其余的内容。

If it's your own program you're debugging, I'd think you'd know the class names!

If it's a program for which you don't have the source code, then to run it you must know the class name containing main(). If it's in a jar started with java -jar, the name of that class is in the manifest inside the jar.

But in fact you're running jdb ClassName, so you know you'll be running method ClassName.main(). Right?

If it's a servlet in a web service, the class of the servlet is in web.xml.

So in any of those cases you should at least be able to get the very first method. Once there, you can find the rest.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文