Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Debugging Unveiled: Exploring Debugger Internal...

Debugging Unveiled: Exploring Debugger Internals to Make You a Better Developer

​​Debuggers are indispensable tools for Java developers, empowering them to conquer bugs and unravel complex systems. But have you ever wondered how they work? Curious about the implementation of features like conditional breakpoints and remote debugging? Wondering about all the cool features in modern IDEs and how they are implemented and how IDEs even communicate with your JVM?

Join me for a deep dive into debuggers, unlocking their secrets to maximize their potential. Gain invaluable insights and elevate your debugging game in this illuminating talk.

Johannes Bechberger

October 12, 2023
Tweet

More Decks by Johannes Bechberger

Other Decks in Technology

Transcript

  1. Public If debugging is the process of removing software bugs,

    then programming must be the process of putting them in. — Edsger Dijkstra “
  2. Public ➜ java LineCounter.java lines LineCounter.java Exception in thread "main"

    java.nio.file.NoSuchFileException: lines at java.base/sun.nio.fs.UnixException.translateToIOException(UnixException.java:92) at java.base/sun.nio.fs.UnixException.rethrowAsIOException(UnixException.java:106) at java.base/sun.nio.fs.UnixException.rethrowAsIOException(UnixException.java:111) at java.base/sun.nio.fs.UnixFileSystemProvider.newByteChannel(UnixFileSystemProvider.java:261 at java.base/java.nio.file.Files.newByteChannel(Files.java:379) at java.base/java.nio.file.Files.newByteChannel(Files.java:431) at java.base/java.nio.file.spi.FileSystemProvider.newInputStream(FileSystemProvider.java:420) at java.base/java.nio.file.Files.newInputStream(Files.java:159) at java.base/java.nio.file.Files.newBufferedReader(Files.java:2897) at java.base/java.nio.file.Files.readAllLines(Files.java:3392) at java.base/java.nio.file.Files.readAllLines(Files.java:3433) at LineCounter.countLines(LineCounter.java:24) at LineCounter.main(LineCounter.java:10)
  3. Public public static void main(String[] args) throws IOException { Path

    file = Path.of(args[0]); int count = switch (args[0]) { case "lines" -> countLines(file); case "code_lines" -> countCodeLines(file); default -> { System.err.println("Usage: java ... " + "<lines|code_lines> <file>"); System.exit(1); yield 0; } }; System.out.println(count); }
  4. Public public static int countLines(Path file) { return Files.readAllLines(file).size(); }

    public static int countCodeLines(Path file) { int count = 0; for (String line : Files.readAllLines(file)) { if (!line.isBlank() && !line.startsWith("//")) { count++; } } return count; }
  5. Public Why debug? •Find and fix bugs! •Analyze the code

    •Add more logging on the fly •Change behavior on the fly •Analyze memory issues •And much more — Egor Ushakov “
  6. Public IntelliJ JDI JDWP Agent JVM Java JDWP JVMTI VSCode

    Java Debug Server DAP Java JPDA eclipse debugger based
  7. Public ➜ java -agentlib:jdwp=transport=dt_socket,server=y, suspend=y,address=*:5005,onjcmd=y src/test/java/OnThrowAndJCmd.java & ➜ echo $!

    # get pid # wait some time and then start debugging on demand ➜ jcmd $! VM.start_java_debugging jcmd 97145 VM.start_java_debugging 97145: Debugging has been started. Transport : dt_socket Address : *:5005
  8. Public ➜ java -agentlib:jdwp=transport=dt_socket,server=y, suspend=y,address=*:5005,onthrow=Ex, launch=exit src/test/java/OnThrowAndJCmd.java # or ➜

    java -agentlib:jdwp=transport=dt_socket,server=y, suspend=y,address=*:5005,onuncaught=y, launch=exit src/test/java/OnThrowAndJCmd.java
  9. Public Exception in thread "event-handler" java.lang.NullPointerException: Cannot invoke "com.sun.jdi.ObjectReference.referenceType()" because

    the return value of "com.sun.jdi.event.ExceptionEvent.exception()" is null at jdk.jdi/com.sun.tools.example.debug.tty.TTY.exceptionEvent(TT Y.java:171) at jdk.jdi/com.sun.tools.example.debug.tty.EventHandler.exceptio nEvent(EventHandler.java:295) at jdk.jdi/com.sun.tools.example.debug.tty.EventHandler.handleEv ent(EventHandler.java:133) at jdk.jdi/com.sun.tools.example.debug.tty.EventHandler.run(Even tHandler.java:78) at java.base/java.lang.Thread.run(Thread.java:1583)
  10. Public cbEarlyException handler ex.class == "Ex"? initialize(env, thread, EI_EXCEPTION) yes

    start debugging session debugger attached set standard Exception handler send Ex exception event ignore no send Exception event 2nd Ex throw 1st Ex throw null pointers
  11. Public Packets length id flags (= 0) command set command

    data 4 bytes 4 bytes 1 byte 1 bytes 1 bytes variable Request/Event length id flags (= 0x80) error code data 4 bytes 4 bytes 1 byte 1 bytes variable Request/Event
  12. Public Debugger JVM Set breakpoint JVM supports breakpoints Do you

    know any runtimes that don't? Python < 3.12
  13. Public JVMTI is a terrible API, we should get rid

    of it as much as possible. — Anonymous Java Architect “
  14. Public Implement a Caching and Prefetching tunnel Cloud Application Developer

    Debugger Internet get x x get x x get y y get y y JDWP
  15. Public Implement a Caching and Prefetching tunnel Cloud Application Developer

    Debugger Internet get x x JDWP get y y C o n get x x JDWP get y y C o n get x,y x, y get x,y x, y HTTP
  16. Public But... IntelliJ JDI JDWP Agent JVM Java JDWP JVMTI

    VSCode Java Debug Server DAP Java JPDA
  17. Public Are methods with breakpoints interpreted? Yes, they are deoptimized.

    https://github.com/openjdk/jdk/blob/edcc559f09364da3692862e1f3d0636aa8eec1d4/ src/hotspot/share/code/codeCache.cpp#L1425
  18. Public Are methods interpreted during single stepping? Yes, they are

    deoptimized. https://github.com/openjdk/jdk/blob/d31391597433cf275fc615e0148c48c34acf6e11/ src/hotspot/share/prims/jvmtiEventController.cpp#L205
  19. Public # of resources on this topic? None, just one

    from Apache Harmony https://harmony.apache.org/subcomponents/drlvm/breakpoints_and_ss.html 2011
  20. Public Does forced return, execute finalize blocks? No No further

    instructions are executed in the called method. Specifically, finally blocks are not executed. “ — JDWP documentation for JDK 17