Debug a Java Application Without Starting the Jvm with Debug Arguments

Debug a java application without starting the JVM with debug arguments

You may be able to use jsadebugd (JDK) to attach a debug server to the process (available on Windows with the Debugging Tools for Windows). It is marked as experimental, so you may want to try it out on a test machine first.

Usage:

jsadebugd <pid>
jdb -connect sun.jvm.hotspot.jdi.SADebugServerAttachingConnector:debugServerName=localhost

The connector name withe arg can be found using jdb -listconnectors.

Enable java remote debug in code

The address property specifies host (optionally) and port (only the port if host is left out). So address=5005 specifies the port 5005 in your case. If you want your program to wait until you connect your debugger, switch suspend=n to suspend=y.

Edit:
Maybe I misunderstood your question. In case you want to enable debugging programmatically, this won't be possible as the debugging facility JPDA is not exposing a Java API nor any other way to start and stop it programmatically.

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

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.

Is it possible to enable debug for a Java process after it is started without debug

The answer is no - if the JVM was not started with the debug option you can't connect to its debug port.

There may be special profiler type JVMs that allow it, but it's not possible with any of the standard JMVs - for obvious security reasons.

How to debug Java code running inside native code-created JVM?

In order to use full Java debugging features of Eclipse, you need to start JVM with JDWP agent, that is, pass the following JVM argument:

-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=9999

JDWP requires some JVM TI cababilities that available only at VM startup. This means you cannot attach debugger later if JVM is started without JDWP agent.

I'd suggest to set some command-line argument or environment variable to indicate that your C++ program should add the above agentlib argument to vmArgs before creating JVM. Then you will be able to attach Java debugger to the port specified in address parameter.

JVM debug connector internals and security

I will focus on the SADebugServerAttachingConnector case.

Here are some more quotes from the Java 11 version of the document you linked to:

SA Debug Server Attaching Connector

This connector can be used by a debugger application to debug a process or core file on a machine other than the machine upon which the debugger is running.

This connector uses RMI to communicate with a 'debug server' running on the remote machine.
Before the attach() method on this connector is called, the debug server must be started on the remote machine
and told what process or corefile is to be debugged.

A process to be debugged need not have been started in debug mode(ie, with -agentlib:jdwp or -Xrunjdwp).


1) Why do debug options like Xrunjdwp exist in the first place then?

The SA Debug Server method allows you to debug a Java process where you either didn't want to launch with an agent (e.g. for security reasons), or you didn't have the foresight to do that.

Conversely, the agent approach is for cases where you don't want the hassle of setting up an SA Debug Server to debug your Java app.

It is "horses for courses" ... as they say.

2) How does SADebugServerAttachingConnector work without taking a port number in the arguments?

Your debugger is using the RMI default port to talk to the SA Debug Server. The SA Debug Server is attaching to the target JVM using a mechanism that is known to the server and the target. It is likely to be an OS-specific mechanism under the hood. For example, on Linux it could use ptrace(2) APIs. Network sockets and ports need not be involved.

3) Documentation does not say anything about requiring root privileges. Is it not a serious privilege escalation vulnerability to allow arbitrary debugging of jvm instances not started in debug mode, by unprivileged users?

The documentation states that you need to specifically set up the linkage between the SA Debug Server and the target VM. This is done when you start the SA Debug Server.

OS-level access controls won't allow a non-root SA Debug Server to use (for example) ptrace syscalls access a Java process belonging to another user / user id. And the OS won't let you start a root SA Debug Server unless you already have root privilege. So there is no escalation of privilege, either in the root or non-root cases.

(Modulo any undisclosed or unpatched OS-level root escalation bugs ... of course.)

Attach IntelliJ IDEA debugger to a running Java process

Yes! Here is how you set it up.

Run Configuration

Create a Remote run configuration:

  1. Run -> Edit Configurations...
  2. Click the "+" in the upper left
  3. Select the "Remote" option in the left-most pane
  4. Choose a name (I named mine "remote-debugging")
  5. Click "OK" to save:

Sample Image

JVM Options

The configuration above provides three read-only fields. These are options that tell the JVM to open up port 5005 for remote debugging when running your application. Add the appropriate one to the JVM options of the application you are debugging. One way you might do this would be like so:

export JAVA_OPTS="-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5005"

But it depends on how your run your application. If you're not sure which of the three applies to you, start with the first and go down the list until you find the one that works.

You can change suspend=n to suspend=y to force your application to wait until you connect with IntelliJ before it starts up. This is helpful if the breakpoint you want to hit occurs on application startup.

Debug

Start your application as you would normally, then in IntelliJ select the new configuration and hit 'Debug'.

Sample Image

IntelliJ will connect to the JVM and initiate remote debugging.

You can now debug the application by adding breakpoints to your code where desired. The output of the application will still appear wherever it did before, but your breakpoints will hit in IntelliJ.

How to debug remote JVM exposed by ngrok tunnel

I've found the solution. The issue was in the Remote Debugger configuration. When specifying the host, you must not include the protocol. Once I changed tcp://2.tcp.eu.ngrok.io to 2.tcp.eu.ngrok.io, it worked!



Related Topics



Leave a reply



Submit