6

Within a Java process, I want to access the JDI (Java Debugging Interface) of that same process.

I make the following assumptions:

  • The process is being executed within the debugger (in Intelli/J)
  • I use the Oracle JVM 8
  • I run Linux (no portability is needed)

That is, I want to do something like:

import com.sun.jdi.*
import com.sun.jdi.connect.*

VirtualMachine vm = new SelfConnector().attach()

(Except, of course, that there is no such object.)

How can I connect to my own VM?

Why do I want that?

I wish to write a function findObj that finds an object via its unique ID. For example, if in the Intelli/J debugger I see a variable "x = {Something@1234}", then I want to be able to add a watch expression "findObj(1234)" that finds and return the object. That way, I will be able to see the object #1234 even after the variable x has been changed or I have left the current stack frame.

I believe that I can implement this function once I have access to the JDI for the current process.

[EDIT: It does not answer the question, but it solves my use case: In Intellij/J you can "mark" objects, and use these markers in watch expressions.]

What have I tried?

I have tried to connect to the process itself via a SocketAttach AttachingConnector using the hostname and port that Intelli/J supplies in the -agentlib:jdwp=transport=dt_socket,address=127.0.0.1:39469,suspend=y,server=n argument when starting the Java process in a debug session. (Following roughly the method described here.) I get:

Exception in thread "main" java.net.ConnectException: Connection refused

Probably because Intelli/J is already connected and one cannot connect twice to that port? [EDIT: Intellij/J starts the jwdp agent with parameter server=n which means the process will do the connecting. Hence the connection refused. But further experiments show that even if one uses server=y, at most one connection is accepted.]

Another approach was to use a ProcessAttach AttachingConnector. In that case, I got:

Exception in thread "main" java.io.IOException: Not a debuggee, or not listening for debugger to attach
Dominique Unruh
  • 1,248
  • 8
  • 23
  • The problem is the uniqueID as you put it is not actually unique. The hashCode is NOT unique and the numeric number after the @ symbol is actually the Hex of the HashCode. https://docs.oracle.com/javase/7/docs/api/java/lang/Object.html http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/6-b27/java/lang/Object.java#Object.toString%28%29 – Johnny V Aug 07 '16 at 22:04
  • @JohnnyV I did not mean the hash code. The debugger (at least in Intelli/J) shows in the variable view: `x = {Type@123} Type@abcdef`. Here 123 is the unique ID that I mean, and `abcdef` is the `hashCode` you refer to. `{Type@123}` is generated by the debugger, and `Type@abcdef` is just the output of `toString()`. – Dominique Unruh Aug 07 '16 at 23:53
  • I think the first thing to do is figure out how Intelli/J is coming up with {klass@1234} because I'm not aware of any unique ID in the instance memory. http://stackoverflow.com/questions/26357186/what-is-in-java-object-header – Johnny V Aug 08 '16 at 00:01
  • A unique ID is available via the JDI, see the method uniqueID here: https://docs.oracle.com/javase/8/docs/jdk/api/jpda/jdi/index.html?com/sun/jdi/ObjectReference.html. I assume that this is the ID that Intelli/J uses, although I can't be sure. – Dominique Unruh Aug 08 '16 at 18:40
  • If you look at VirtualMachineImpl.java line #1069 in HotSpot you see that the uniqueID is most likely the memory address of the object. That said, objects can move memory address at any given point in time. – Johnny V Aug 08 '16 at 19:04
  • The comment in VirtualMachineImpl.java might be incorrect. The source of ObjectReferenceImpl.uniqueID() indicates that the uniqueID is a sequential number (see https://github.com/JetBrains/jdk8u_hotspot/blob/b37ae60/agent/src/share/classes/sun/jvm/hotspot/jdi/ObjectReferenceImpl.java#L64) – Dominique Unruh Aug 08 '16 at 22:40
  • The confusing part is the JDK version of ObjectReferenceImpl takes a long as an constructor parameter: https://github.com/JetBrains/jdk8u_jdk/blob/01abac6ceb2d4c7679ab19acbaee94e0b9ed1828/src/share/classes/com/sun/tools/jdi/ObjectReferenceImpl.java#L92 Back tracking that code leads to the conversion of Oop to a long somehow. – Johnny V Aug 08 '16 at 23:41
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/120464/discussion-between-dominique-unruh-and-johnny-v). – Dominique Unruh Aug 08 '16 at 23:52

0 Answers0