Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Retrieve ID of instance, like Eclipse's debugger does

Eclipse has a convenient feature when you're paused in the debugger that shows an ID for every instance. They appear to be sequential and based on when an instance was allocated:

Example of IDs in a debugging session

I find these extremely useful when I'm digging into a substantial problem, as they're usually small integers that are a lot easier to remember than the full hash codes, or some other internal ID. They're a very quick check for "is this still the object I think it is?" when you're stepping through complex and deep callstacks.

Are these allocation IDs tracked by the jvm itself, or are they something Eclipse is providing through some unknown mechanism?

Is there any way to get at them from code, so that I can temporarily put them in log messages while debugging?

I don't really want to add an ID field to every object, there's many good reasons why that is a Bad Idea.

like image 272
Stik Avatar asked Feb 16 '26 23:02

Stik


1 Answers

Are these allocation IDs tracked by the jvm itself, or are they something Eclipse is providing through some unknown mechanism?

Object IDs are generated by JDWP agent. JDWP agent is a library that exposes JVM debugging capabilities to external Java debuggers (like Eclipse IDE) through the JDWP protocol.

The agent is typically started with the JVM by the command line option -agentlib:jdwp= or -Xrunjdwp.

They appear to be sequential and based on when an instance was allocated

IDs are generated on demand when the agent needs to send an object reference to the debugger. They are not related to object creation time or something. Java objects initially have no assigned IDs.

Is there any way to get at them from code

As I said above, object IDs do not exist until the agent exchanges object references with the debugger.

But you may generate your own IDs for objects using IdentityHashMap or similar. Here is a simplest way to create such IDs:

private static final Map<Object, Long> map = new IdentityHashMap<>();

private static long nextId;

public static long getId(Object o) {
    synchronized (map) {
        Long id = map.get(o);
        if (id == null) {
            map.put(o, id = ++nextId);
        }
        return id;
    }
}

Of course, this implementation is not perfect, since it uses a global lock and stores objects forever. A better solution would be a kind of WeakIdentityConcurrentMap.

In fact, this is exactly how JDWP agent generates object IDs. It keeps an internal hash table that maps an object to a sequentially inceremented integer, and uses reference counting for removal. See commonRef.c

like image 62
apangin Avatar answered Feb 19 '26 11:02

apangin



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!