Auto Reattach for Java Debug
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.
The Problem
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.
The Solution
This extension monitors your Java debug sessions and automatically reattaches when the JDWP port becomes available again after a restart. No more manual reconnections!
Features
- ✅ 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)
- ✅ Detailed Logging: Comprehensive logs in the Output panel for troubleshooting
- ✅ Zero Dependencies: No tasks or complex configurations required
Requirements
- VS Code 1.99.3 or higher
- Debugger for Java extension
- Java application with JDWP enabled
Quick Start
.vscode/launch.json
:
{
"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
}
]
}
.vscode/settings.json
:
{
"javaAutoReattach.enabled": true,
"javaAutoReattach.configurations": [
{
"launchName": "Micronaut Dev Mode"
}
]
}
3. Start Debugging
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
- Checks every
retryIntervalMs
if the JDWP port is accepting connections
- Continues for up to
maxWaitTimeMs
milliseconds
- Each individual connection attempt has a fixed 1-second TCP timeout
- Automatically reconnect the debug session
Extension Settings
This extension contributes the following settings:
Global 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. The extension will keep trying to connect until this timeout is reached. (default: 30000
= 30 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)
Configuration Array
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 config
retryIntervalMs
(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
Advanced Configuration Examples
Multiple services with different settings:
{
"javaAutoReattach.enabled": true,
"javaAutoReattach.maxWaitTimeMs": 30000,
"javaAutoReattach.retryIntervalMs": 500,
"javaAutoReattach.configurations": [
{
"launchName": "Attach to API",
"enabled": true,
"maxWaitTimeMs": 45000 // This service takes longer to restart
},
{
"launchName": "Attach to Worker",
"enabled": true
},
{
"launchName": "Attach to Test",
"enabled": false // Disabled for this config (useful for override user settings)
}
]
}
User + Workspace Settings Merge:
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.
Status Bar
The extension shows its current state in the status bar:
- ⚪ Idle: Extension is ready, no active debug session being monitored
- 🔌 Monitoring: Actively watching a debug session
- 🔄 Waiting for target...: 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)
Troubleshooting
Extension not working?
- 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)
Debug session doesn't reconnect?
- 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
- The extension logs all session termination events with full details
- Check if
javaAutoReattach.enabled
is true
- Verify the configuration is in the
configurations
array
- Increase the
maxWaitTimeMs
if your app takes longer to restart (e.g., 60000
for 60 seconds)
App takes too long to restart?
- Increase
maxWaitTimeMs
to give your app more time (e.g., 60000
for 60 seconds)
- Check your application logs for startup errors or build issues
JDWP Handshake Warning
During automatic reattachment, you may see the following warning in your Java application logs:
Debugger failed to attach: handshake failed - connection prematurally closed
This is harmless and occurs because the extension checks if the JDWP port is available before attempting to reattach. The warning appears briefly during the port availability check and does not affect debugging functionality. The reattachment will succeed normally right after this warning.
Technical Details: The warning is generated when the extension performs a TCP connection test to detect if the JDWP port is ready. JDWP attempts to initiate its handshake protocol when it accepts the connection, but the test connection closes immediately, resulting in this warning. This is an inherent limitation when checking TCP port availability for JDWP services.
Known Limitations
1. Launch Configurations with Dynamic Ports
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.
2. Other Limitations
- The extension cannot differentiate between manual stop and app restart - it always attempts to reconnect
Enjoy seamless Java debugging! 🚀