Java调试器:是否可以有选择地暂停线程?

6
在我作为一名C/C++程序员的过去生活中,有些平台和调试器组合可以选择性地暂停线程。在触发断点后,可以发出命令(或在GUI中点击)来挂起/恢复线程。在进一步的步骤/下一步/运行/继续命令之后,挂起的线程不会执行任何指令。
今天的任何JVM或Java IDE都可以实现这个功能吗?我使用IntelliJ,但我没有看到这个功能,也无法通过Google找到任何信息。
澄清一下:
  • 我不是在询问断点的线程策略,例如,挂起当前线程还是所有线程。我知道JVM调试器的这个功能。
  • 开发环境是原始的:我使用IntelliJ Java IDE,并且可以访问相关的源代码。
  • 最后,我意识到“Java调试器”是一个比较模糊的术语。据我所知,Sun发布了一种调试器用于与JVM通信的调试格式。也许每个JVM(IBM vs Sun vs IcedTea vs ???)都支持不同的调试能力,但我只熟悉Sun/Oracle JVM。

    嗨Kevin,你是否对你正在运行的代码有控制权,并且它只是一个特定的点?因为如果你准备修改代码,你可以使用boolean threadSuspendedif (!threadSuspended)模式,并在调试器中手动设置该布尔值。很抱歉我找不到更好的答案。 - vikingsteve
    1
    一些有关于编程暂停/恢复被弃用的相关讨论在这里:http://docs.oracle.com/javase/8/docs/technotes/guides/concurrency/threadPrimitiveDeprecation.html - vikingsteve
    Eclipse有一个名为“条件断点”的功能,可以在触发断点并暂停当前线程之前评估某些任意Java代码。因此,在那里执行一些还会挂起其他线程的代码。不知道IntelliJ是否具有类似的功能。 - SpaceTrucker
    也许这是不可能的。我假设JVM在所有支持它的平台上都使用pthread。如果是这样,请参见:https://dev59.com/Y2DVa4cB1Zd3GeqPgLtR#9408451 - kevinarpe
    @vikingsteve:这是一个不错的解决方法。我建议你将其作为单独的答案添加。 - kevinarpe
    4个回答

    3

    在jdb中,您可以轻松地挂起单个线程(请参见下文)。我喜欢使用IntelliJ作为Java编辑器。但是,就其调试器而言,它不是很好,但也不算太差。

    Initializing jdb ...
    > run
    Nothing suspended.
    > threads
    Group system:
      (java.lang.ref.Reference$ReferenceHandler)0x141 Reference Handler cond. waiting
      (java.lang.ref.Finalizer$FinalizerThread)0x140  Finalizer         cond. waiting
      (java.lang.Thread)0x13f                         Signal Dispatcher running
      (java.lang.Thread)0x401                         Java2D Disposer   cond. waiting
      (java.lang.Thread)0x804                         TimerQueue        cond. waiting
    Group main:
      (java.lang.Thread)0x322                         AWT-AppKit        running
      (java.lang.Thread)0x323                         AWT-Shutdown      cond. waiting
      (java.awt.EventDispatchThread)0x5ec             AWT-EventQueue-0  cond. waiting
      (java.util.TimerThread)0x750                    Timer-0           cond. waiting
      (java.lang.Thread)0x7fd                         DestroyJavaVM     running
    > suspend 0x5ec             
    > threads
    Group system:
      (java.lang.ref.Reference$ReferenceHandler)0x141 Reference Handler cond. waiting
      (java.lang.ref.Finalizer$FinalizerThread)0x140  Finalizer         cond. waiting
      (java.lang.Thread)0x13f                         Signal Dispatcher running
      (java.lang.Thread)0x401                         Java2D Disposer   cond. waiting
      (java.lang.Thread)0x804                         TimerQueue        cond. waiting
    Group main:
      (java.lang.Thread)0x322                         AWT-AppKit        running
      (java.lang.Thread)0x323                         AWT-Shutdown      cond. waiting
      (java.awt.EventDispatchThread)0x5ec             AWT-EventQueue-0  waiting in a monitor
      (java.util.TimerThread)0x750                    Timer-0           cond. waiting
      (java.lang.Thread)0x7fd                         DestroyJavaVM     running
    > where 0x5ec
      [1] java.lang.Object.wait (native method)
      [2] java.lang.Object.wait (Object.java:485)
      [3] java.awt.EventQueue.getNextEvent (EventQueue.java:558)
      [4] java.awt.EventDispatchThread.pumpOneEventForFilters (EventDispatchThread.java:263)
      [5] java.awt.EventDispatchThread.pumpEventsForFilter (EventDispatchThread.java:211)
      [6] java.awt.EventDispatchThread.pumpEventsForHierarchy (EventDispatchThread.java:201)
      [7] java.awt.EventDispatchThread.pumpEvents (EventDispatchThread.java:196)
      [8] java.awt.EventDispatchThread.pumpEvents (EventDispatchThread.java:188)
      [9] java.awt.EventDispatchThread.run (EventDispatchThread.java:122)
    AWT-EventQueue-0[1] where 0x322
    Current thread isn't suspended.
    AWT-AppKit[1] resume 0x5ec
    AWT-AppKit[1] where 0x5ec
    Current thread isn't suspended.
    AWT-EventQueue-0[1]
    

    1
    我的脑袋差点就要爆炸了。真是太棒了!这个答案的关键在于:它证明了JVM调试线协议支持此功能。现在需要向JetBrains提交请求... - kevinarpe
    1
    读者们:请在此处为IntelliJ的功能请求点赞:http://youtrack.jetbrains.com/issue/IDEA-79921 - kevinarpe

    2

    1
    Eclipse至少可以使用Oracle VM做到这一点,但我猜所有的虚拟机都可以。尝试在调试器中选择一个线程(应该有一个显示所有运行线程的视图)。然后,挂起按钮应该只挂起此线程而不是所有线程。

    1

    您是否有控制运行的代码,并且它只是一个特定点?

    由于如果您准备修改代码,您可以使用布尔 threadSuspended if (! threadSuspended) 模式,并在调试器中手动设置该布尔值。

    这是一个实用的解决方法 - 不完全是您要求的功能,但可能会完成工作;)


    网页内容由stack overflow 提供, 点击上面的
    可以查看英文原文,
    原文链接