From karellen-jdb-mcp
Debug a Java application using JDB. Attaches to a running JVM, sets breakpoints, inspects state, and navigates execution to find the root cause of bugs.
How this skill is triggered — by the user, by Claude, or both
Slash command
/karellen-jdb-mcp:jdb-debugThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Use this skill when the user wants to debug a Java application, investigate an exception,
Use this skill when the user wants to debug a Java application, investigate an exception, inspect runtime state, or understand execution flow.
jdb must be installed and on PATH (comes with the JDK)suspend=y pauses the JVM until the debugger attaches (recommended for startup debugging)suspend=n lets the JVM run immediately (for attaching to a live process)You (Claude) will typically start the JVM yourself before connecting. The JDWP agent stanza
varies by launcher. Pick a free port (e.g. 5005) and use suspend=y so the JVM waits for
you to attach.
javajava -agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=*:5005 \
-cp target/classes com.example.Main
mvn test -Dmaven.surefire.debug="-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=*:5005"
Or the built-in shorthand (uses port 5005 by default):
mvn -Dmaven.surefire.debug test
For Failsafe integration tests replace surefire with failsafe.
MAVEN_OPTS="-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=*:5005" \
mvn exec:java -Dexec.mainClass=com.example.Main
./gradlew test --debug-jvm # uses port 5005 by default, suspend=y
Add to the task or pass via env:
JAVA_OPTS="-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=*:5005" \
./gradlew run
Tycho Surefire uses the same property as Maven Surefire:
mvn verify -Dmaven.surefire.debug="-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=*:5005"
Or with the tycho.testArgLine property:
mvn verify -Dtycho.testArgLine="-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=*:5005"
mvn spring-boot:run -Dspring-boot.run.jvmArguments="-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=*:5005"
Or with Gradle:
./gradlew bootRun --args='--debug' # or pass JAVA_OPTS
As a fallback, this environment variable is picked up by every JVM:
JAVA_TOOL_OPTIONS="-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=*:5005" \
<any-command-that-starts-a-jvm>
Use jdb_launch to start the JVM with ${JDB_PORT} substitution (allocates a random port):
jdb_launch(["java", "-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=*:${JDB_PORT}",
"-cp", "target/classes", "com.example.Main"])
Or for Maven tests:
jdb_launch(["mvn", "test",
"-Dmaven.surefire.debug=-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=*:${JDB_PORT}"])
Then connect with wait_timeout to wait for the JVM to start. When there is exactly
one launched process, jdb_connect auto-resolves the port — no need to pass it:
jdb_connect(wait_timeout=30)
If you launched multiple JVMs or are connecting to a manually started JVM, specify the port:
jdb_connect(port=5005, wait_timeout=30)
Similarly, all debugging tools auto-resolve the port when only one session is active.
When multiple sessions are active, pass port= to select which session to use.
Pass jdb_path if jdb is not on PATH. Pass sourcepath to enable source listing.
Pass trackallthreads=True on JDK 20+ to track virtual threads.
jdb_breakpoint_set("com.example.MyClass:42") # line breakpoint
jdb_breakpoint_set("com.example.MyClass.myMethod") # method breakpoint
jdb_breakpoint_set("com.example.MyClass.myMethod(int)") # overloaded method
For exception debugging:
jdb_catch("java.lang.NullPointerException") # break on NullPointerException
jdb_catch("*", filter_type="uncaught") # break on any uncaught exception
For field watchpoints:
jdb_watch("com.example.MyClass.myField") # break on field write
jdb_watch("com.example.MyClass.myField", access_type="access") # break on field read
Execution commands are fire-and-forget: they return immediately once the JVM resumes.
If a breakpoint or exception is hit within a few seconds, the stop event is returned
directly. Otherwise, the tool returns reason="resumed" and you should use
jdb_suspend() or wait for the next breakpoint to examine state.
If the JVM was started with suspend=y:
jdb_run() # start execution (returns immediately)
Or if already running:
jdb_cont() # continue execution (returns immediately)
If jdb_run or jdb_cont returns reason="resumed", call jdb_wait_for_event to
block until the next breakpoint, exception, or program exit:
jdb_wait_for_event(timeout=120) # blocks until stop event or timeout
jdb_where() — see the call stackjdb_locals() — see all local variablesjdb_print("expression") — evaluate any Java expressionjdb_dump("objectRef") — show all fields of an objectjdb_list() — see source code at current positionjdb_threads() — list all threadsjdb_step() — step into (enter method calls)jdb_next() — step over (skip over method calls)jdb_step_up() — step out (run until current method returns)jdb_up() / jdb_down() — navigate the call stack without steppingjdb_classes() to find loaded classesjdb_methods("com.example.MyClass") to discover available methodsjdb_fields("com.example.MyClass") to discover fieldsjdb_class_info("com.example.MyClass") to see class hierarchyjdb_set("variable", "newValue") to modify state and test hypothesesFor deadlock analysis:
jdb_threads() — find stuck threadsjdb_threadlocks() — see what locks a thread holds and waits forjdb_lock("objectRef") — see who owns a lock and who's waitingjdb_thread("threadId") then jdb_where() — inspect each thread's stackjdb_session_list() — list all active debug sessions with port and JDK versionjdb_launch_list() — list all launched JVM processes with statusjdb_launch_status(port=<port>) — check if a specific launched process is still runningjdb_disconnect()
jdb_launch_stop(port=<port>)
Or when debugging multiple JVMs:
jdb_disconnect(port=<port>)
jdb_launch_stop(port=<port>)
jdb_launch to start JVMs rather than Bash. It handles port allocation,
${JDB_PORT} substitution, and process detachment.jdb_connect,
jdb_launch*, and jdb_session_list require an active session.jdb_catch for exception debugging — it's more effective than guessing where to
set breakpoints.jdb_version for feature availability. Thread-filtered breakpoints require
JDK 13+, virtual thread tracking requires JDK 20+.jdb_exclude to skip library code when stepping. By default, JDB skips
java., javax., sun., com.sun., jdk.*.jdb_monitor("locals") to auto-print locals at every stop for hands-free
debugging.npx claudepluginhub karellen/claude-plugins --plugin karellen-jdb-mcpDebugs Java applications using JDB CLI: attach to running JVMs with JDWP, launch new ones under debugger, set breakpoints, step code, inspect variables/threads, diagnose exceptions.
Debug live Java applications via JDWP with breakpoints, state inspection, expression evaluation, variable mutation, logpoints, and field watchpoints.
Guides debugging Java applications via IntelliJ debugger: breakpoints, stepping, expression evaluation, and runtime state inspection. Includes preflight checks for MCP tool availability.