2

I'm using JNA. The Pointer class represents a native pointer. It seems quite common to access the pointer's address which seems to be the peer member variable. However, they made sure you can't query it. Why? What's the recommended way to getting it if you want to work with it?

I wrote the following "hack":

public static long getBaseAddress(Pointer pointer)
{
    String stringPointer = pointer.toString();
    String[] splitStringPointer = stringPointer.split("@");
    int expectedSplitLength = 2;

    if (splitStringPointer.length != expectedSplitLength)
    {
        throw new IllegalStateException("Expected a length of "
                + expectedSplitLength + " but got " + splitStringPointer.length);
    }

    String hexadecimalAddress = splitStringPointer[1].substring("0x".length());
    return parseLong(hexadecimalAddress, 16);
}

But isn't there a proper way other than abusing the toString() method for grabbing the address?

I want to use Reflection even less than the approach above since it is also brittle.

BullyWiiPlaza
  • 17,329
  • 10
  • 113
  • 185
  • There are good reasons outlined by Stephen as to why this shouldn't be done. That said, when faced with a choice between parsing toString and reflection, you should almost certainly prefer reflection. Although both are brittle, reflection is much more suitable for inspecting members of a class as you are doing here, as compared to parsing toString. – nanofarad Aug 12 '18 at 05:24
  • @AndreyAkhmetov: Can you please link to the statement by Stephen (whoever he is)? – BullyWiiPlaza Aug 12 '18 at 09:15
  • Stephen deleted his answer, but it was up on this post at the time of writing of my comment. I don't know why he deleted it and I can't validate it to be true, but my statement about reflection vs toString still stands. – nanofarad Aug 12 '18 at 16:38

2 Answers2

4

While subclassing (as in technomage's answer) works, it's unnecessary. Pointer.nativeValue(p) will give you p's peer.

And as in my comment to the other answer, "Don't use this unless you know what you're doing." It's generally not needed for anything inside JNA. Only if you actually need the memory address for some other purpose is the peer value truly relevant. You can iterate an offset from 0 to accomplish idioms like the code sample in the link you posted in your comment there.

The Pointer's getters all take an offset argument, and you can also simply return a pointer to an offset from the original peer value using share().

Daniel Widdis
  • 8,424
  • 13
  • 41
  • 63
2

Make a subclass of Pointer and you can do whatever you'd like with the protected field.

Generally, you shouldn't access the value directly, the intent of making the field protected is exactly to make it hard to make such mistakes inadvertently.

technomage
  • 9,861
  • 2
  • 26
  • 40
  • How is accessing the value directly a mistake if you want to keep incrementing it like in this `C++` code example? https://stackoverflow.com/a/28232548/3764804 1. Get the value 2. Increment 3. Make a new `Pointer` object 4. Repeat It's perfectly fine, isn't it? – BullyWiiPlaza Aug 13 '18 at 21:53
  • 1
    @BullyWiiPlaza not so much a mistake as a "generally you shouldn't". As the Javadoc for the constructor with the peer states, "Don't use this unless you know what you're doing." There are other ways (e.g., offsets, `share()`, etc.) to access memory at an offset from the original pointer that I find preferable. YMMV. – Daniel Widdis Aug 14 '18 at 22:16