A volte può essere utile debuggare un’applicazione Java già deployata in ambiente di produzione o che semplicemente sta “girando” su una macchina che non sia quella di sviluppo.

Come fare in questi casi?

Piuttosto semplice, grazie agli strumenti di debug remoto messi a disposizione dai più diffusi IDE in circolazione.

In questo post vediamo come sfruttare le funzionalità di remote debugging di IntelliJ IDEA ed Eclipse.

Premessa

Prima di sfrecciare a debuggare con entusiasmo tutte le nostre applicazioni, è importante sapere una cosa: per poter effettuare il debug remoto di un’applicazione Java è necessaria un’opportuna configurazione della stessa. In particolare, l’applicazione dovrà esporre una porta su cui resterà in ascolto di eventuali richieste di connessione.

Questo implica principalmente due cose:

  • è inutile cercare di connettersi ad applicazioni che non siano state preventivamente configurate per il remote debug;
  • il debug mode influenza le prestazioni della JVM, per cui non è consigliato utilizzarlo (o mantenerlo costantemente attivo) in ambienti di produzione.

Configurare il debug mode

L’abilitazione del debug remoto per un applicazione Java avviene in fase di avvio. Ad esempio:

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

Piccola nota A differenti versioni della JVM corrispondono alcune differenze nella modalità di abilitazione del debug mode. Io sto utilizzando la sintassi compatibile con Java 5 - 8.

L’opzione -agentlib:jdwp permette di specificare delle sotto-opzioni per la connessione all’applicazione in fase di debug. In particolare:

  • transport=dt_socket: indica che la comunicazione tra l’applicazione e il debugger avverrà tramite socket TCP/IP.
  • server=y: indica che la JVM si comporterà come server di debug, mentre il debugger fungerà da client.
  • Il parametro suspend permette di indicare se la JVM deve sospendere l’avvio dell’applicazione in attesa della connessione da parte del debugger. Nel nostro caso questo non serve: l’applicazione può avviarsi normalmente ed accettare connessioni successive (valore n).
  • address=5005: consente di specificare la porta su cui l’applicazione rimarrà in ascolto di richieste di connessione.

Una volta avviata la nostra applicazione è il momento di scoprire come debuggarla.

Debug con IntelliJ IDEA

Per effettuare il debug remoto con IntelliJ IDEA dovremo creare un’apposita Debug Configuration.

IntelliJ IDEA - Edit Configurations...

Dal menù Run, selezioniamo la voce Edit Configurations…; si aprirà la finestra corrispondente che consentirà di aggiungere una nuova configurazione. In particolare, facciamo click sul + in alto a sinistra per aggiungere una configurazione di tipo Remote.

IntelliJ IDEA - Remote debug configuration

Esaminiamo le opzioni di base presenti nella tab Configuration (per un elenco completo dei parametri configurabili rimando alla documentazione di IntelliJ IDEA):

Come al solito, IntelliJ IDEA si dimostra estremamente smart e ci aiuta a definire gli argomenti che dovremo fornire alla JVM in fase di avvio (v. Command line arguments for remote JVM). La stringa viene costruita dinamicamente selezionando le opzioni di debug presenti nella finestra di configurazione.

In particolare:

  • Debugger mode: Attach to remote JVM - imposta le opzioni server=y e suspend=n;
  • Transport: socket - corrisponde a transport=dt_socket;
  • Port: 5005 - va ad impostare l’opzione address=5005;
  • è inoltre possibile impostare la versione della JVM utilizzata in modo da avere la corrispondente versione corretta della stringa degli argomenti.

Il campo Host non viene inserito nelle opzioni per la JVM, ma serve al debugger per sapere a quale macchina connettersi (quella su cui risiede l’applicazione da debuggare). Sarà inoltre necessario selezionare il modulo corrispondente al progetto su cui sarà effettuato il debug (Use module classpath).

A questo punto possiamo copiare le opzioni per la JVM e salvare/applicare le configurazioni inserite.

Una volta avviata la nostra applicazione con il debug mode abilitato, ci spostiamo nuovamente in IntelliJ IDEA: selezioniamo la run configuration appena creata e lanciamo il debug.

IntelliJ IDEA - Remote run configuration

Se tutto va liscio, dovreste visualizzare questo messaggio nella Console:

Connected to the target VM, address: 'localhost:5005', transport: 'socket'

E, cosa più importante, noterete che i vostri breakpoint verranno “agganciati” dal debugger, esattamente come succederebbe effettuando il debug in locale.

Debug con Eclipse IDE

Anche in Eclipse, la procedura per il debug remoto è piuttosto semplice.

Analogamente a quanto fatto per IntelliJ IDEA, si parte dalla creazione di una Debug Configuration: facendo click col tasto destro sul progetto, selezioniamo Debug As → Debug Configurations….

Eclipse - Debug Configurations

A questo punto selezioniamo dalla lista, la tipologia Remote Java Application e, facendo click col destro, scegliamo di creare una nuova configurazione.

Eclipse - Remote Java Application

Anche in questo caso ci limiteremo a definire i soli parametri fondamentali per poter effettuare il debug.

La tab Connect presenta le opzioni che conosciamo già, necessarie al debugger per connettersi all’applicazione remota.

Eclipse - Remote Java Application Settings

Al termine della configurazione facciamo click su Apply per salvare i valori impostati, o direttamente su Debug per procedere con la connessione all’applicazione precedentemente avviata.

In conclusione

Il remote debug può tornare utile in molte situazioni in cui non sia possibile lavorare direttamente in ambiente di sviluppo. (Un esempio interessante è il caso di applicazioni containerizzate tramite Docker.)

In questo post abbiamo visto come effettuare il debug remoto di un’applicazione Java sfruttando il debug mode della JVM e gli strumenti forniti da IntelliJ IDEA ed Eclipse.

Spero di esservi stato utile e… buon debug! 😉

A presto,

David