Java: local and remote JVM debugging — JDK 8, 9 and later

There is no need to tell about importance of JVM debugging some feature at development, test or sometimes even at production environment.
The Java Debug Wire Protocol (JDWP) and java agent library included into JDK provides the ability to debug java applications.

JVM <=8

By default JDWP agent listens all interfaces so both local and remote connections for JVM debug or code invocation could be established.

  • local mode means that you are trying to connect from the same machine where the JVM is running, e.g. you laptop.
  • remote mode stands for running app at some remote host e.g. myappsdomain.com and connect to that JVM from your laptop.

Note that while enabling remote debugging you definitely should think about safety and do not expose that port to everyone.

To enable port 8001 for local and remote debug at JDK 8 and below add the following agentlib option while starting your app:

$ java -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=8001 Test
Listening for transport dt_socket at address: 8001
...

This message means that JDWP agent was successfully initialized and is now listening at port 8001 for incoming local or remote debug connection.

Now you can connect to your app’s JVM from your favourite IDE,
e.g. Intellij Idea
Intellij Idea jvm debug configuration screen

To enable port 8001 only for local debug use
-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=127.0.0.1:8001

Debug JVM 9+

Since Java 9 JDWP agent listens only local network interface by default so remote connections would be rejected.

JDK 9 Release Notes

The JDWP socket connector has been changed to bind to localhost only if no ip address or hostname is specified on the agent command line. A hostname of asterisk (*) may be used to achieve the old behavior which is to bind the JDWP socket connector to all available interfaces; this is not secure and not recommended.

So for JDK 9 and later to enable both local and remote for all interfaces use
-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:8001

Note that asterisk wildcard was introduced at JDK 9.
At JDK 8 and below an attempt to run JDWP debug with *:8001 will cause error at startup:


$ java -version
java version "1.8.0_40"
Java(TM) SE Runtime Environment (build 1.8.0_40-b27)
Java HotSpot(TM) 64-Bit Server VM (build 25.40-b25, mixed mode)

$ java -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:8001 Test
ERROR: transport error 202: gethostbyname: unknown host
ERROR: JDWP Transport dt_socket failed to initialize, TRANSPORT_INIT(510)
JDWP exit error AGENT_ERROR_TRANSPORT_INIT(197): No transports initialized [debugInit.c:750]
FATAL ERROR in native method: JDWP No transports initialized, jvmtiError=AGENT_ERROR_TRANSPORT_INIT(197)
Abort trap: 6