Search code examples
javadebuggingjvmbreakpointsjdi

How to set a breakpoint in Java code with instrumentation?


So, opcode 202 (1100 1010) is reserved for a breakpoint event according to the Java specification. I tried inserting a breakpoint opcode in a Java method with the help of the ASM library:

targetWriter.visitInsn(202);

but the JVM crashed with error message: no original bytecode found in ... at bci 0. After searching in the Hotspot implementation I found where this error is thrown:

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;
}

So according to this, the method needs to know about the breakpoint (it stores all its breakpoints in a list) but it doesn't know about it if it is directly set via code instrumentation.

Is there a workaround (without JVMTI) to set a breakpoint event with code instrumentation?


Solution

  • Being a reserved opcode according to JVMS §6.2, breakpoint opcode is exclusively for the JVM internal use. It should not occur in the user generated class files.

    When you inject the breakpoint instruction manually, JVM does not know what to do with it, and it does not know what original bytecode has been replaced.

    Breakpoints are set with JVM TI SetBreakpoint event, and notifications are received via Breakpoint event callback. If you don't want to use JVM TI directly, the alternative is JDWP. Most Java IDEs use JDWP for debugging.