Remote debugging a Java application - java

I have a java application running on linux machine. I run the java application using the following:
java myapp -Xdebug -Xrunjdwp:server=y,transport=dt_socket,address=4000, suspend=n
I have opened port 4000 for TCP on this Linux machine. I use eclipse from Windows XP machine and try to connect to this application. I have opened the port in windows also.
Both machines are on the LAN but I can't seem to connect the debugger to the Java application. What am I doing wrong?

Edit: I noticed that some people are cutting and pasting the invocation here. The answer I originally gave was relevant for the OP only. Here's a more modern invocation style (including using the more conventional port of 8000):
java -agentlib:jdwp=transport=dt_socket,server=y,address=8000,suspend=n <other arguments>
Original answer follows.
Try this:
java -Xdebug -Xrunjdwp:server=y,transport=dt_socket,address=4000,suspend=n myapp
Two points here:
No spaces in the runjdwp option.
Options come before the class name. Any arguments you have after the class name are arguments to your program!

For JDK 1.3 or earlier :
-Xnoagent -Djava.compiler=NONE -Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=6006
For JDK 1.4
-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=6006
For newer JDK :
-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=6006
Please change the port number based on your needs.
From java technotes
From 5.0 onwards the -agentlib:jdwp option is used to load and specify
options to the JDWP agent. For releases prior to 5.0, the -Xdebug and
-Xrunjdwp options are used (the 5.0 implementation also supports the -Xdebug and -Xrunjdwp options but the newer -agentlib:jdwp option is preferable as the JDWP agent in 5.0 uses the JVM TI interface to the
VM rather than the older JVMDI interface)
One more thing to note, from JVM Tool interface documentation:
JVM TI was introduced at JDK 5.0. JVM TI replaces the Java Virtual Machine Profiler Interface (JVMPI) and the Java Virtual Machine Debug Interface (JVMDI) which, as of JDK 6, are no longer provided.

Answer covering Java >= 9:
For Java 9+, the JVM option needs a slight change by prefixing the address with the IP address of the machine hosting the JVM, or just *:
-agentlib:jdwp=transport=dt_socket,server=y,address=*:8000,suspend=n
This is due to a change noted in https://www.oracle.com/java/technologies/javase/9-all-relnotes.html#JDK-8041435.
For Java < 9, the port number is enough to connect.

Steps:
Start your remote java application with debugging options as said in above post.
Configure Eclipse for remote debugging by specifying host and port.
Start remote debugging in Eclipse and wait for connection to succeed.
Setup breakpoint and debug.
If you want to debug from start of application use suspend=y , this will keep remote application suspended until you connect from eclipse.
See Step by Step guide on Java remote debugging for full details.

I'd like to emphasize that order of arguments is important.
java -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=8000 -jar app.jar command opens debugger port,
but java -jar app.jar -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=8000 command doesn't. It will pass everything after app.jar as command-line arguments.

This is how you should setup Eclipse Debugger for remote debugging:
Eclipse Settings:
1.Click the Run Button
2.Select the Debug Configurations
3.Select the “Remote Java Application”
4.New Configuration
Name : GatewayPortalProject
Project : GatewayPortal-portlet
Connection Type: Socket Attach
Connection Properties:
i) localhost ii) 8787
For JBoss:
1.Change the /path/toJboss/jboss-eap-6.1/bin/standalone.conf in your vm as follows:
Uncomment the following line by removing the #:
JAVA_OPTS="$JAVA_OPTS -agentlib:jdwp=transport=dt_socket,address=8787,server=y,suspend=n"
For Tomcat :
In catalina.bat file :
Step 1:
CATALINA_OPTS="-Xdebug -Xrunjdwp:transport=dt_socket,address=8000,server=y,suspend=n"
Step 2:
JPDA_OPTS="-agentlib:jdwp=transport=dt_socket,address=8000,server=y,suspend=n"
Step 3: Run Tomcat from command prompt like below:
catalina.sh jpda start
Then you need to set breakpoints in the Java classes you desire to debug.

for everybody that has the problem that if you really do remote debugging from 1 machine to the other then using :
-agentlib:jdwp=transport=dt_socket,server=y,address=8000,suspend=n
is not enough because that binds now (at least on unix/osx machines) to localhost so you can only connect to it from localhost.
If you try to remote debug this then you will get connection refused for this. From i think Java 9 on you need to do:
-agentlib:jdwp=transport=dt_socket,server=y,address=*:8000,suspend=n
or give an ip that it needs to bind on for hat *

Related

Cannot debug Java application with Eclipse

I have a Java (Vert.x) application on my machine that I am trying to attach Eclipse to for debugging.
I usually start the Java application in my console like so:
java -jar build/libs/my-app.jar
Upon reading about debugging, I am attempting to start the app as follows:
java -jar build/libs/my-app.jar -Xdebug -Xrunjdwp:transort:transport=dt_socket,address=8001,server=y,suspend=n
The app seems to start up in the console fine when I run this.
I then go into Eclipse, and try to connect to the app via debugging via Run -> Debug Configurations. This is what my debug configuration looks like:
When I click debug, I get an error box that pops up and says that the connection is refused (I covered the name of my real app). See below:
What am I doing wrong? How can I get remote debugging to connect to my app with Eclipse?
According to my reading of this JDWP documentation, your -Xrunjdwp option is incorrect:
-Xrunjdwp:transort:transport=dt_socket,address=8001,server=y,suspend=n
should be
-Xrunjdwp:transport=dt_socket,address=8001,server=y,suspend=n
If your system has multiple IP addresses, there could be some confusion about which IPs the agent is listening for connections on. You could force a specific address; e.g.
-Xrunjdwp:transport=dt_socket,address=127.0.0.1:8001,server=y,suspend=n
and use the matching IP and port in the Eclipse debug connection parameters.
AND ... as Dave Thompson spotted ... all JVM options must be placed before the -jar argument. (Anything after the -jar name.jar will be treated as command line arguments for your application.)

Debugging Java classes which are called from Windows batch files

I have a java project A which is dependent on another project B. I want to debug the java class of project B while starting the batch files from project A. How can I achieve this in Eclipse ?
You can attach tell java to allow connecting to debug by passing the command line parameters (legacy style):
-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=8000
The newer style (JVM TI interface used):
-agentlib:jdwp=transport=dt_socket,address=8000,server=y,suspend=n
You should then be able to attach eclipse to debug:
Configure Eclipse for remote debugging by specifying host and port.
host: localhost, port:8000
See this answer: What are Java command line options to set to allow JVM to be remotely debugged?

visualvm/jvisualvm: not supported for this JVM

I wanted to monitor the JVM of wildfly running as service with jvisualvm/visualvm but I fail to do this. I tried the following things:
setting the %TMP% and %TEMP% to C:\Windows\Temp (wildfly console
tells me this for java.io.tmpdir)
running a console with sysinternals
pstools as system account: psexec -i -s cmd.exe and started visualvm
from within this new console (checked that the temp folders are
correctly set).
In both cases under local applications the process of wildfly was listed but visualvm only told me "not supported for this jvm".
As soon as I run wildfly from the cli, visualvm has no problems and shows me everything. There is only the jdk from oracle installed (with the corresponding jre).
How can I monitor the process of wildfly running as service (local system account)? Why is it not working with the solutions above?
Thanks a lot (for reading)
Thank you Salah
With your hint (local JMX connection) I've managed to make it work by using the following command for visualvm (no change of TMP/TEMP variables in cmd):
visualvm.exe -cp:a "<path-to-wildfly>\bin\client\jboss-client.jar"
and adding the path to the jmx console (don't forget to set the username/pw for the admin gui)
service:jmx:http-remoting-jmx://localhost:9990

visualvm cannot see a java process launched from cygwin

If I start a java process in a cygwin console, and then launch visualVm, the later cannot see the former.
If I start the same process in a Dos console visualvm sees it fine. I am in jdk1.6.0_25. This happens both in win7 32b, and in win7 64b with a 64b jvm.
Anyone can think of an explanation/workaround?
I fixed the problem by running VisualVM from within Cygwin. If you prefer not to profile using a remote JMX connection, you can run both VisualVM and your Java program using Cygwin:
Open the Cygwin Console window, navigate to visual_vm.exe and run that file from within the Cygwin environment.
I had the same problem. The vm was not shown automatically but I was able to connect via "Add JMX Connection", using hostname and jmx.remote.port...
On VisualVM go to File -> Add JMX Connection
localhost:3333
Add vm parameter at startup e.g.:
-Dcom.sun.management.jmxremote.port=3333
-Dcom.sun.management.jmxremote.ssl=false
-Dcom.sun.management.jmxremote.authenticate=false
VisualVM can automatically detect local applications running under the same user. So one explanation can be that cygwin process is running under the different user. Make sure that both VisualVM and monitored application is running under JDK 6 update 25. JDK 6 update 25 has a fix for the following JDK bug #6938627, which can affect your case.
The opposite approach to #seanhodges answer is to launch the application to debug with a modified environment, pointing it back to your Windows User Temp directory
For example if you normally do:
./gradlew run
And say your TEMP directory on Windows (according to your User environment variables) is:
T:\Temp
You can do one of these instead:
TMP=T:\\Temp ./gradlew run
TMP=/cygdrive/t/Temp ./gradlew run
(they both seem to work)

What are Java command line options to set to allow JVM to be remotely debugged?

I know there's some JAVA_OPTS to set to remotely debug a Java program.
What are they and what do they mean ?
Before Java 5.0, use -Xdebug and -Xrunjdwp arguments. These options will still work in later versions, but it will run in interpreted mode instead of JIT, which will be slower.
From Java 5.0, it is better to use the -agentlib:jdwp single option:
-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=1044
Options on -Xrunjdwp or agentlib:jdwp arguments are :
transport=dt_socket : means the way used to connect to JVM (socket is a good choice, it can be used to debug a distant computer)
address=8000 : TCP/IP port exposed, to connect from the debugger,
suspend=y : if 'y', tell the JVM to wait until debugger is attached to begin execution, otherwise (if 'n'), starts execution right away.
I have this article bookmarked on setting this up for Java 5 and below.
Basically run it with:
-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=1044
For Java 5 and above, run it with:
-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=1044
If you want Java to wait for you to connect before executing the application, replace suspend=n with suspend=y.
Since Java 9.0 JDWP supports only local connections by default.
http://www.oracle.com/technetwork/java/javase/9-notes-3745703.html#JDK-8041435
For remote debugging one should run program with *: in address:
-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:8000
For java 1.5 or greater:
java -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5005 <YourAppName>
For java 1.4:
java -Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=5005 <YourAppName>
For java 1.3:
java -Xnoagent -Djava.compiler=NONE -Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=5005 <YourAppName>
Here is output from a simple program:
java -Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=1044 HelloWhirled
Listening for transport dt_socket at address: 1044
Hello whirled
java
java -Xdebug -Xrunjdwp:transport=dt_socket,server=y,address=8001,suspend=y -jar target/cxf-boot-simple-0.0.1-SNAPSHOT.jar
address specifies the port at which it will allow to debug
Maven
**Debug Spring Boot app with Maven:
mvn spring-boot:run -Drun.jvmArguments=**"-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8001"
Command Line
-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=PORT_NUMBER
Gradle
gradle bootrun --debug-jvm
Maven
mvn spring-boot:run -Drun.jvmArguments="-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=PORT_NUMBER
Here is the easiest solution.
There are a lot of environment special configurations needed if you are using Maven. So, if you start your program from maven, just run the mvnDebug command instead of mvn, it will take care of starting your app with remote debugging configurated. Now you can just attach a debugger on port 8000.
It'll take care of all the environment problems for you.
-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=PORT_NUMBER
Here we just use a Socket Attaching Connector, which is enabled by default when the dt_socket transport is configured and the VM is running in the server debugging mode.
For more details u can refer to : https://stackify.com/java-remote-debugging/
If you are using java 9 or higher, to remotely debug (which is also the case when you use docker at local) you have to provide --debug *:($port). Because from java 9 --debug ($port) will only allow to debug at local, not remotely.
So, you can provide command in docker-compose like
command: -- /opt/jboss/wildfly/bin/standalone.sh --debug *:8787

Categories

Resources