A lightweight extension that automatically reconnects your Java debug session when your application restarts during development.
🤖 Built with Vibe Coding — Fully developed through AI-assisted pair programming, combining human direction with AI execution.
When developing Java applications in "dev mode" (like Micronaut mn:run, Spring Boot DevTools, or similar tools), the watch mode restarts the JVM when code changes are detected. This terminates the JDWP socket and drops your debug session, forcing you to manually reconnect after every change - interrupting your workflow.
This extension monitors your Java debug sessions and automatically reattaches when the JDWP port becomes available again after a restart. No more manual reconnections!
- ✅ Automatic Reattach: Seamlessly reconnects when your Java app restarts
- ✅ Multiple Sessions: Support for debugging multiple services simultaneously
- ✅ Smart Configuration: Auto-detects host/port from launch.json
- ✅ Status Visibility: Status bar shows current state (Idle, Monitoring, Waiting, Reattached)
- ✅ Proper JDWP Protocol: Performs complete JDWP handshake and graceful disconnect to prevent server-side warnings
- ✅ Detailed Logging: Comprehensive logs in the Output panel for troubleshooting
- ✅ Zero Dependencies: No tasks or complex configurations required
- ✅ Safety Limits: Monitors up to 50 concurrent sessions to prevent memory leaks
- VS Code 1.99.3 or higher
- Debugger for Java extension
- Java application with JDWP enabled
- Trusted Workspace: The extension requires a trusted workspace to function. VS Code will prompt you to trust the workspace when you first open it.
.vscode/launch.json:
.vscode/settings.json:
{
"javaAutoReattach.enabled": true,
"javaAutoReattach.configurations": [
{
"launchName": "Micronaut Dev Mode"
}
]
}After your launch starts, the extension will:
- Monitor your debug session
- Detect when it terminates (e.g., app restart)
- Verifies if this session is configured for auto-reattach (javaAutoReattach.configurations)
- Wait for the JDWP port to become available
- Repeatedly checks if the JDWP port is accepting connections and validates JDWP handshake
- Checks every
retryIntervalMsif the JDWP port is accepting connections - Continues for up to
maxWaitTimeMsmilliseconds - Each connection attempt has a 500ms socket timeout (suitable for local and Docker environments)
- Automatically reconnect the debug session
This extension contributes the following settings:
javaAutoReattach.enabled: Enable/disable auto-reattach globally (default:true)javaAutoReattach.maxWaitTimeMs: Maximum time in milliseconds to wait for the JDWP port after a session terminates. Note: This measures JVM restart time (typically 1-3 seconds), NOT full application startup time. JDWP is ready as soon as the JVM starts. (default:5000= 5 seconds)javaAutoReattach.retryIntervalMs: Interval in milliseconds between each port availability check. Lower values = more responsive but higher CPU usage. Higher values = less responsive but lower CPU usage. (default:500= 0.5 seconds)
javaAutoReattach.configurations: Array of debug configurations to monitor
Each configuration object supports:
launchName(required): Name of the launch configuration in launch.json (must match exactly)enabled(optional): Enable for this specific config (default:true)maxWaitTimeMs(optional): Override global maxWaitTimeMs for this configretryIntervalMs(optional): Override global retryIntervalMs for this config
Array Merge Behavior:
- Workspace settings take priority over user settings
- Configurations from user settings are merged with workspace settings (not replaced)
- If both define the same
launchName, the workspace version is used
Important: maxWaitTimeMs measures JVM restart time, not full application startup time.
- ✅ JDWP is ready as soon as the JVM process starts (typically 1-3 seconds)
- ✅ Your Spring Boot/Micronaut app may take 20-30 seconds to fully initialize
- ✅ But debugging is available immediately after JVM initialization
- ✅ Native JVM restart: 1-3 seconds
- ✅ Most development scenarios: 2-4 seconds
- ✅ Provides 2-3x safety margin
⚠️ You're using Docker Desktop (Mac/Windows) - try10000(10s)⚠️ You're using DevContainers with slow I/O - try10000(10s)⚠️ You see timeout warnings in the Output panel consistently⚠️ Your machine is very slow or heavily loaded
The extension enforces a maximum of 60 seconds. If JVM hasn't started in 60 seconds, there's likely a real problem with your application.
{
"javaAutoReattach.enabled": true,
"javaAutoReattach.maxWaitTimeMs": 5000,
"javaAutoReattach.retryIntervalMs": 500,
"javaAutoReattach.configurations": [
{
"launchName": "Attach to API",
"enabled": true,
"maxWaitTimeMs": 10000 // Docker Desktop - needs more time
},
{
"launchName": "Attach to Worker",
"enabled": true
},
{
"launchName": "Attach to Test",
"enabled": false // Disabled for this config (useful for override user settings)
}
]
}User Settings (apply to all projects):
{
"javaAutoReattach.enabled": true,
"javaAutoReattach.configurations": [
{ "launchName": "Attach to Common Service" }
]
}Workspace Settings (project-specific):
{
"javaAutoReattach.configurations": [
{ "launchName": "Attach to Project API" }
]
}Result: Both configurations will be monitored.
The extension shows its current state in the status bar:
When monitoring a single debug session:
- ⚪ Idle: Extension is ready, no active debug session being monitored
- 🔌 Monitoring: Actively watching a debug session
- 🔄 Waiting: Port is down, waiting for app to restart
- ✅ Reattached: Successfully reconnected
⚠️ "[config]" uses dynamic port (not supported): A launch config with dynamic port allocation was detected (hover for details)
When monitoring multiple debug sessions simultaneously:
- The status bar shows an aggregated view (e.g., "2 sessions, 1 waiting")
- Hover over the status bar to see detailed information for each session (config name, host, port, and state)
- The icon reflects the most important state: waiting > reattached > monitoring
- Check if the workspace is trusted: The extension requires a trusted workspace. If you see "Disabled" in the status bar, check if VS Code is asking you to trust the workspace.
- Check the Output panel:
View > Output > Auto Reattach Java Debug - Verify you're using an
"attach"configuration (not"launch"with dynamic port) - Verify your configuration matches the launch.json name exactly
- Ensure JDWP is enabled on your Java application
- Check if the port is correct (default: 5005)
- Check if you see this warning in the Output:
"launch configurations with dynamic port allocation are not supported"- If yes, you need to use an
"attach"configuration instead
- If yes, you need to use an
- The extension logs all session termination events with full details
- Check if
javaAutoReattach.enabledistrue - Verify the configuration is in the
configurationsarray - Increase the
maxWaitTimeMsif your app takes longer to restart (e.g.,60000for 60 seconds)
- Increase
maxWaitTimeMsto give your app more time (e.g.,60000for 60 seconds) - Check your application logs for startup errors or build issues
The extension only works with "request": "attach" configurations or "request": "launch" with a fixed port.
❌ Not Supported:
{
"type": "java",
"request": "launch", // Dynamic port allocation
"mainClass": "com.example.App"
// No port specified - VS Code allocates dynamically
}✅ Supported:
{
"type": "java",
"request": "attach", // Fixed port
"hostName": "localhost",
"port": 5005,
"preLaunchTask": "spring-dev-mode"
}✅ Also Supported (Launch with Fixed Port):
{
"type": "java",
"request": "launch",
"mainClass": "com.example.App",
"vmArgs": "-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=5005"
// Or specify port directly if your debugger supports it
}Why? When VS Code launches a Java application, it allocates a JDWP port dynamically at runtime. The VS Code API does not expose this runtime port information, making it impossible for the extension to know which port to reconnect to.
- The extension cannot differentiate between manual stop and app restart - it always attempts to reconnect
Enjoy seamless Java debugging! 🚀
{ "version": "0.2.0", "configurations": [ { "name": "Micronaut Dev Mode", "type": "java", "request": "attach", "hostName": "localhost", "port": 5005, "preLaunchTask": "micronaut-dev-mode" // ./mvnw mn:run or ./gradlew run --continuous } ] }