Skip to content

A lightweight VS Code extension that automatically reconnects your Java debug session when your application restarts

License

Notifications You must be signed in to change notification settings

marlonpatrick/auto-reattach-for-java-debug

Repository files navigation

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)
  • 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

Requirements

  • 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.

Quick Start

1. Configure Your Launch

.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
    }
  ]
}

2. Configure Your Settings

.vscode/settings.json:

{
  "javaAutoReattach.enabled": true,
  "javaAutoReattach.configurations": [
    {
      "launchName": "Micronaut Dev Mode"
    }
  ]
}

3. Start Debugging

After your launch starts, the extension will:

  1. Monitor your debug session
  2. Detect when it terminates (e.g., app restart)
  3. Verifies if this session is configured for auto-reattach (javaAutoReattach.configurations)
  4. Wait for the JDWP port to become available
    • Repeatedly checks if the JDWP port is accepting connections and validates JDWP handshake
    • Checks every retryIntervalMs if the JDWP port is accepting connections
    • Continues for up to maxWaitTimeMs milliseconds
    • Each connection attempt has a 500ms socket timeout (suitable for local and Docker environments)
  5. 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. 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)

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

Understanding maxWaitTimeMs

Important: maxWaitTimeMs measures JVM restart time, not full application startup time.

Why the distinction matters

  • 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

Default value (5 seconds) is sufficient for

  • ✅ Native JVM restart: 1-3 seconds
  • ✅ Most development scenarios: 2-4 seconds
  • ✅ Provides 2-3x safety margin

Increase maxWaitTimeMs only if

  • ⚠️ You're using Docker Desktop (Mac/Windows) - try 10000 (10s)
  • ⚠️ You're using DevContainers with slow I/O - try 10000 (10s)
  • ⚠️ You see timeout warnings in the Output panel consistently
  • ⚠️ Your machine is very slow or heavily loaded

Maximum allowed value: 60 seconds

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.

Advanced Configuration Examples

Multiple services with different settings

{
  "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 + 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:

Single Session

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)

Multiple Sessions

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

Troubleshooting

Extension not working?

  1. 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.
  2. Check the Output panel: View > Output > Auto Reattach Java Debug
  3. Verify you're using an "attach" configuration (not "launch" with dynamic port)
  4. Verify your configuration matches the launch.json name exactly
  5. Ensure JDWP is enabled on your Java application
  6. 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

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! 🚀

About

A lightweight VS Code extension that automatically reconnects your Java debug session when your application restarts

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published