【问题标题】:How to set a breakpoint in Java code with instrumentation?如何使用检测在 Java 代码中设置断点?
【发布时间】:2020-09-30 02:56:41
【问题描述】:

因此,根据 Java 规范,操作码 202 (1100 1010)reserved for a breakpoint event。我尝试借助 ASM 库在 Java 方法中插入断点操作码:

targetWriter.visitInsn(202);

但 JVM 崩溃并显示错误消息:no original bytecode found in ... at bci 0。在 Hotspot 实现中搜索后,我发现了引发此错误的位置:

Bytecodes::Code Method::orig_bytecode_at(int bci) const {
  BreakpointInfo* bp = method_holder()->breakpoints();
  for (; bp != NULL; bp = bp->next()) {
    if (bp->match(this, bci)) {
      return bp->orig_bytecode();
    }
  }
  {
    ResourceMark rm;
    fatal(err_msg("no original bytecode found in %s at bci %d", name_and_sig_as_C_string(), bci));
  }
  return Bytecodes::_shouldnotreachhere;
}

因此,根据这一点,该方法需要知道断点(它将所有断点存储在一个列表中),但如果它是通过代码检测直接设置的,则它不知道。

是否有解决方法(不使用 JVMTI)来使用代码检测设置断点事件?

【问题讨论】:

  • 不,断点操作码不应该直接设置。为什么要避免 JVM TI?当 JVM 到达断点时,你期望会发生什么?
  • @apangin,我认为如果我直接设置断点,JVM 会停在那里并且 Intellij IDEA 的调试器会自动触发。但我不确定后者。

标签: java debugging jvm breakpoints jdi


【解决方案1】:

根据JVMS §6.2,作为保留操作码,断点操作码仅供JVM内部使用。它不应该出现在用户生成的类文件中。

当你手动注入断点指令时,JVM不知道怎么处理它,也不知道替换了什么原始字节码。

断点通过 JVM TI SetBreakpoint 事件设置,通知通过 Breakpoint 事件回调接收。如果您不想直接使用 JVM TI,则可以选择 JDWP。大多数 Java IDE 使用 JDWP 进行调试。

【讨论】:

  • 规范确实列出了它,例如参见this page,以及impdep1impdep2。这有点奇怪,考虑到任何未使用的操作码都可以在内部被实现使用(事实上,HotSpot 在内部也使用其他操作码)。
  • 也值得链接,JVMS §6.2
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-02-06
  • 2022-01-18
  • 2011-04-26
  • 2017-02-26
  • 2014-08-21
相关资源
最近更新 更多