0

Let's say I have a java class

class NativeInterface{
    public static native void access(Object obj);
}

And all I want to do is access the 2nd byte (for example) of that object.

I.e. I want to do something like this:

#include<jni.h>
#include "NativeInterface.h"
#include <stdio.h>

using byte = unsigned char;

/*
* Class:     NativeInterface
* Method:    access
* Signature: (Ljava/lang/Object)V
*/
JNIEXPORT void JNICALL Java_NativeInterface_access(JNIEnv* env, jclass _obsolete, jobject obj){
    byte byte_array[] = obj;
    printf("%c",byte_array[2]);
}

Now obviously, this doesn't work. obj may not even be the java object. (jobject is defined in the jni.h and I haven't yet figured out what it does.)

So how do I do this?

(Trying this naive attempt will result in

error: initializer fails to determine size of ‘byte_array’
     byte byte_array[] = obj;
                         ^~~~

, btw.)

User1291
  • 7,664
  • 8
  • 51
  • 108
  • you can't assign to an array nor can you initialize it from something different than an array initializer! Consult your documentation what exactly `jobject` **is**, something like `char *objbytes = obj` might work. –  Nov 13 '17 at 09:44

1 Answers1

2

"obj may not even be the java object"

You almost figured it out yourself. It's just a bit stronger than that. Java has Garbage Collection. For that reason alone, you know that obj is not the java object, but merely a handle that refers to that object as it's shuffled around in memory by the Garbage Collector.

You now see the fundamental flaw in your question: "get memory address of java object" presumes that you get a useful value. But even if you could get an address, it would be unreliable from the first clocktick after you get it.

MSalters
  • 173,980
  • 10
  • 155
  • 350
  • I agree that it's not the java object, I disagree that if I could get an address, it would be "unreliable from the first clocktick". See my follow-up question: https://stackoverflow.com/questions/47267806/substituting-jvm-oop-pointer-in-c – User1291 Nov 13 '17 at 15:28
  • @User1291: You're looking at behind-the-scenes JNI code there which prevents the object from moving while JNI is assigning an `Int`. – MSalters Nov 13 '17 at 15:30
  • I don't see what you mean. If you are correct, then how does the unsafe implementation get away with not doing anything to "prevent the object from moving" while it's executing? – User1291 Nov 13 '17 at 15:42
  • @User1291: That's another incorrect assumption. JNI is integral to the JVM, and it does prevent objects from moving. That's not so strange, the JVM must prevent objects from moving regardless of who is calling a method on the object. – MSalters Nov 14 '17 at 09:29
  • Thank you. Does it matter that I'm trying to eventually execute it within an RTM transaction (see https://stackoverflow.com/questions/47220275/how-to-use-unsafe-in-jni)? I'm not entirely sure, but I'd assume at least one value read in the process of acquiring an address will have to change on a move, s.t. the transaction aborts and could be retried. So if we transactionally resolve the address and access/modify the location within the same transaction ... that should work? – User1291 Nov 14 '17 at 09:41
  • @User1291: It probably matters, but that looks horribly complicated. I would never trust such a solution to be reliable. – MSalters Nov 14 '17 at 10:03
  • No argument there. Unfortunately, that doesn't change the fact I'll have to try and make something like that work. Still, thanks for your time and the informations. – User1291 Nov 14 '17 at 10:07