Skip to main content
skill GitHub Copilot official · GitHub

java-debugging — GitHub Copilot skill: debug Java apps

A skill that walks the agent through finding a Java bug: reproduce, narrow down, test one hypothesis, attach a debugger. Useful once logs stop explaining anything.

Install into GitHub Copilot · Skills CLI (Vercel) All methods and platforms ↓
npx skills add github/awesome-copilot --skill java-debugging
Open on GitHub

What java-debugging does

The skill lays out a debugging loop. Reproduce the defect deterministically, minimize it, read the stack trace, then test one falsifiable hypothesis with the least intrusive tool. A log line or logpoint comes before a breakpoint. Finish with a regression test and remove the debug flags and temporary logging.

It covers JDWP attach, jdb commands, launch configs for VS Code and IntelliJ IDEA, debugging Maven Surefire and Failsafe tests, Gradle, Spring Boot and Quarkus dev mode, containers and Kubernetes. Safety gets its own section: JDWP hands full code execution to whoever connects, so the agent binds to 127.0.0.1 instead of *:5005. Version differences are spelled out too — helpful NullPointerException messages are off in JDK 14 and on from JDK 15, and a bare address=5005 listens on all interfaces before JDK 9.

Worth installing if you debug Java or Kotlin and want the agent to keep the debugger off production and out of your build environment. On a non-Java project, skip it.

What it helps with

  • trace a NullPointerException back to its cause in a stack trace
  • attach a debugger to a running JVM over JDWP
  • debug a failing Maven Surefire or Gradle test
  • explain why Spring Boot or Quarkus behaves differently in dev mode
  • test a hypothesis with a logpoint instead of restarting the app

Example prompts for the agent

  • Attach the debugger on 5005 and find out why placeOrder fails
  • Debug OrderServiceTest with mvn test -Dmaven.surefire.debug
  • Why does JDWP listen on all interfaces in the container but only loopback locally?

How to install java-debugging

1Skills CLI (Vercel)

npx skills add github/awesome-copilot --skill java-debugging

2GitHub CLI

gh skill install github/awesome-copilot java-debugging

3Manually: put the files in place

.github/skills/java-debugging/SKILL.md

From the same set554

The whole set →
git-commit official github This skill reviews Git changes, stages related files, and creates Conventional Commits. Use it when you want an agent to make one commit or split work into separate commits. GitHub Copilot 47,165installs excalidraw-diagram-generator official github Turn a plain-language description into an Excalidraw diagram. Useful for mapping processes, system structure, and relationships between entities. GitHub Copilot 31,639installs multi-stage-dockerfile official github This skill guides GitHub Copilot in writing multi-stage Dockerfiles for different languages and frameworks. Use it when the final runtime image should contain fewer build dependencies. GitHub Copilot 29,688installs documentation-writer official github Skill that turns the agent into a technical writer following the Diátaxis framework: tutorials, how-to guides, reference, and explanation. Proposes structure before writing. GitHub Copilot 27,757installs prd official github Turns a feature idea into a structured PRD with user stories, technical requirements, and risks. Use it when planning a software feature or an AI-powered one. GitHub Copilot 24,035installs refactor official github This skill reshapes existing code without changing its external behavior. Use it for gradual cleanup of large functions, duplication, weak types, and code smells. GitHub Copilot 22,321installs java-springboot official github Gives GitHub Copilot Spring Boot development practices, from project layout to tests and security. Use it when writing or reviewing Java application code. GitHub Copilot 21,272installs create-readme official github This skill reviews a project and creates a structured README.md. Use it when the repository needs clear documentation based on its actual files and code. GitHub Copilot 19,081installs

Similar

email official Vercel Labs Configures email sending via Resend and React Email templates for Vercel apps. It covers API routes and domain verification. CX Codex GP ChatGPT 6installs cron-jobs official Vercel Labs Configures and debugs scheduled Vercel Cron Jobs in vercel.json. Helpful when setting up serverless endpoints that run on a timer. CX Codex GP ChatGPT 6installs ai-gateway official Vercel Labs Guides model routing, failover lists, and caching with Vercel AI Gateway. Useful when managing multiple providers through AI SDK 6. CX Codex GP ChatGPT 6installs podcast-generation microsoft Generates podcast-style audio narratives using Azure OpenAI GPT Realtime Mini over WebSocket. Integrates a FastAPI backend with a React audio player. Claude Code GitHub Copilot 29installs vercel-api official Vercel Labs Connects Codex to Vercel via OAuth and REST API. It helps inspect deployments, fetch build logs, and manage project environment variables directly. CX Codex GP ChatGPT 5installs payments official Vercel Labs Guidance for adding Stripe checkout, subscriptions, and webhook handling to Vercel apps. Use it when building payment flows. CX Codex GP ChatGPT 5installs mcp-builder official anthropics This skill walks through building an MCP server in TypeScript or Python, from reading the protocol spec to writing tests and evaluation questions. Claude Code Claude.ai 130,949installs google-agents-cli-adk-code official Google A reference skill for building ADK agents with tools, callbacks, state, and workflows. Use it when an agent project needs concrete API patterns or code examples. Claude Code CX Codex Cursor +1 511,400installs

Questions about java-debugging

How do I install java-debugging in GitHub Copilot?

Run npx skills add github/awesome-copilot --skill java-debugging or gh skill install github/awesome-copilot java-debugging. The skill file lands at .github/skills/java-debugging/SKILL.md.

What does the java-debugging skill do?

It gives the agent a fixed order of steps for chasing a Java bug and ready-made commands for attaching a debugger to a JVM, tests, Spring Boot, Quarkus and containers.

Is it safe to enable JDWP on a server?

No. JDWP gives full code execution to anyone who connects, so the skill binds it to 127.0.0.1 and uses a tunnel or kubectl port-forward for remote hosts. Never leave a debug agent on production.

Source text

SKILL.md · MIT
---
name: java-debugging
description: 'Debug Java applications systematically: JDWP remote debugging, jdb, VS Code and IntelliJ attach, debugging Maven/Gradle tests, Spring Boot and Quarkus dev mode, containers, breakpoints/logpoints, and reading stack traces. Use when the user needs to find the cause of a Java bug, exception, wrong behavior, or failing test, or asks how to attach a debugger.'
---

# Java Debugging

Find the root cause of a Java defect with a reproducible, hypothesis-driven loop, and attach a debugger safely when logs are not enough.

## Safety rules

- Bind JDWP to loopback only (`127.0.0.1`). Never bind `*:5005` on a reachable network; use an SSH tunnel or `kubectl port-forward` for remote hosts.
- Use `suspend=n` for running applications. `suspend=y` is acceptable only for short local test runs bound to loopback (waiting for the IDE to attach). Never leave a debug agent enabled on production; JDWP gives full code execution to whoever connects.
- Do not attach a debugger to production without explicit user instruction. Prefer reproducing locally or use read-only diagnostics (see the `java-diagnostics` skill).
- `JAVA_TOOL_OPTIONS` is picked up by every JVM started in that environment (build tools, forked test JVMs, child processes), causing `Address already in use` clashes. Prefer scoping the flag to the one process you want to debug.

## Method

Reproduce deterministically, minimize, read the evidence ([stack traces](references/stack-traces.md)), test one falsifiable hypothesis with the least intrusive tool (log line or logpoint before breakpoints), then add a regression test and remove debug flags and temporary logging.

## Version-dependent behavior (verified)

- **Helpful NullPointerException messages** (JEP 358) are off by default in JDK 14 (`-XX:+ShowCodeDetailsInExceptionMessages`) and on by default from JDK 15 (JEP 358 documents the message format). Source: <https://openjdk.org/jeps/358>.
- JDWP bare `address=5005` binds all interfaces before JDK 9 and loopback from JDK 9 (see below).
- Gradle `--debug-jvm` passes a bare address, so on JDK 8 it listens on all interfaces.

## Attach a debugger (JDWP)

Start the JVM:

```bash
java -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=127.0.0.1:5005 -jar app.jar
```

Always write the explicit `127.0.0.1:5005` on every JDK version: a bare `address=5005` listens on all interfaces before JDK 9 and only on loopback from JDK 9. On JDK 8 and older, the `host:port` form may not be honored, so also restrict access with a firewall or tunnel.

Attach with `jdb`:

```bash
jdb -attach 127.0.0.1:5005
# stop in com.example.OrderService.place | stop at com.example.OrderService:42
# cont | next | step | locals | print order | where | catch java.lang.NullPointerException
```

### VS Code (Extension Pack for Java)

`.vscode/launch.json`:

```json
{
  "version": "0.2.0",
  "configurations": [
    {
      "type": "java",
      "name": "Attach to JVM",
      "request": "attach",
      "hostName": "127.0.0.1",
      "port": 5005
    }
  ]
}
```

### IntelliJ IDEA

Run | Edit Configurations | + | Remote JVM Debug; host `127.0.0.1`, port `5005`, debugger mode Attach. The dialog shows the matching JVM argument string.

## Debug tests and frameworks

| Scenario | Command (port 5005) |
|----------|---------------------|
| Maven Surefire unit test | `mvn test -Dmaven.surefire.debug -Dtest=OrderServiceTest` |
| Maven Failsafe IT | `mvn verify -Dmaven.failsafe.debug -Dit.test=OrderIT` |
| Gradle test | `gradle test --debug-jvm --tests '*OrderServiceTest'` |
| Spring Boot (Maven) | `mvn spring-boot:run -Dspring-boot.run.jvmArguments="-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=127.0.0.1:5005"` |
| Spring Boot (Gradle) | Configure `bootRun` as below, then `gradle bootRun` (loopback, no suspend) |
| Quarkus dev mode | `mvn quarkus:dev` (debug port 5005 open by default; `-Ddebug=5006` changes it, `-Ddebug=false` disables) |

Surefire/Failsafe debug mode and `--debug-jvm` suspend until a debugger attaches, which is fine for a local run. Surefire and Failsafe accept a custom agent string instead of the bare flag, e.g. `-Dmaven.surefire.debug="-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=127.0.0.1:5005"`. Verified listeners on `127.0.0.1` (via `lsof -nP -iTCP:5005 -sTCP:LISTEN`) for Gradle 9.7 `--debug-jvm`, Maven Surefire 3.5 `-Dmaven.surefire.debug` and Quarkus 3.40 dev mode on JDK 26; Gradle 7.6.4, 8.0.2 (JDK 17), 8.5 (JDK 21) and 8.14.3 also listened on `127.0.0.1`. Gradle passes a bare `address=5005` (no host), so the bind address comes from the JDK: loopback on JDK 9+, but all interfaces (`0.0.0.0:5005`, checked in an `eclipse-temurin:8-jdk` container with Gradle 7.6.4 and 8.14.3) on JDK 8. Older Gradle/plugin versions were not tested; run the same `lsof` check and use an explicit loopback agent on shared networks or JDK 8.

Explicit Gradle configuration (Gradle 7.6+; `debugOptions.host` was added in 7.6; Kotlin DSL):

```kotlin
tasks.withType<Test> {
    debugOptions { enabled.set(true); host.set("127.0.0.1"); port.set(5005); server.set(true); suspend.set(true) }
}

// BootRun extends JavaExec, not Test; configure it separately when the Boot plugin is applied.
tasks.named<JavaExec>("bootRun") {
    debugOptions { enabled.set(true); host.set("127.0.0.1"); port.set(5005); server.set(true); suspend.set(false) }
}
```

Then run `gradle test --tests '*OrderServiceTest'` or `gradle bootRun`, without `--debug-jvm` (which enables suspension). Configure only the task you are debugging; do not run both listeners on port 5005 at once. For Gradle before 7.6, use `jvmArgs("-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=127.0.0.1:5005")` on the target task instead (`suspend=y` for local tests), without also enabling `debugOptions` or `--debug-jvm`. On JDK 8 and older, retain the firewall/tunnel precaution above.

## Containers

Publish the port to loopback only and let the JVM listen inside the container:

```bash
docker run --rm -p 127.0.0.1:5005:5005 \
  -e JAVA_TOOL_OPTIONS="-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:5005" my-app
```

Inside the container the agent must bind `*` for the port mapping to work, so JDWP (full code execution) is reachable by every other container on the same Docker network; the `127.0.0.1:` mapping only blocks access from other hosts. Use this only on a developer machine where no untrusted containers share the network: run it on a dedicated user-defined network (not the shared default bridge) containing only this container, or keep the agent on `127.0.0.1` inside the container and reach it with `docker exec`/`kubectl port-forward` style forwarding instead of publishing it. For Kubernetes use `kubectl port-forward pod/<name> 5005:5005` against a dev/staging pod only.

## Common pitfalls

- **Hot code replace** only swaps method bodies; adding/removing methods or fields or changing signatures needs a restart (or Quarkus dev mode / Spring DevTools).
- **Missing debug info**: code compiled without `-g` shows unavailable variables (Maven and Gradle include it by default). In lambdas, step into the lambda body.
- **Heisenbugs/races**: pausing changes timing. Prefer logpoints, thread dumps, or JFR; suspend only the current thread, not all threads.
- **Async and reactive code**: stack traces show scheduler frames, not the caller. Use IDE async stack traces, correlation IDs, or Reactor `Hooks.onOperatorDebug()` in dev only.
- **Virtual threads (JDK 21+)**: there can be thousands; use `jcmd <pid> Thread.dump_to_file -format=json file.json` for an overview.
- **Timeouts**: long pauses can trip HTTP, DB, or heartbeat timeouts; raise them locally.
- **toString() side effects**: debugger evaluation calls `toString()`, which may trigger lazy loading or mutate state.

## Optional code-navigation aid

If the Copilot CLI `lsp` tool is configured (see the `lsp-setup` skill), go-to-definition, find-references, and call hierarchy help trace the execution path. It is optional; grep and reading code work as well.

## References

- [Reading stack traces](references/stack-traces.md)
- For runtime symptoms (CPU, memory, deadlocks, slow startup) use the `java-diagnostics` skill.

Official tool docs (prefer them over this skill for the JDK in use; change `21` to your version): `jcmd` <https://docs.oracle.com/en/java/javase/21/docs/specs/man/jcmd.html>, JDK troubleshooting guide <https://docs.oracle.com/en/java/javase/21/troubleshoot/>.

© github · MIT · github/awesome-copilot

See also

Project sponsors

Companies that keep this analytics open
Gold sponsor

Impressions, clicks and code copies — open statistics. We keep the numbers public for the same reason NeBlask itself is public. Become a sponsor