Substituting JVM oop pointer in C++

扶醉桌前 提交于 2019-12-02 16:38:33

问题


So I decided that the "easiest" way to answer my other question is to "simply" look at the implementation of the unsafe in C/C++.

(

In a nutshell, I have an Object base and a long offset in Java, that I'm passing to C/C++ by means of the Java Native Interface (JNI), from where I want to execute the C/C++ equivalent of

unsafe.setInt(base,offset,1)

)

Such an implementation is provided, for example, by the OpenJDK: unsafe.cpp

I don't care about most that's in there, I just want a direct access to values.

So looking at the implementation, I see

#define SET_FIELD(obj, offset, type_name, x) \
  oop p = JNIHandles::resolve(obj); \
  *(type_name*)index_oop_from_field_offset_long(p, offset) = x

Which I hope does what I expect it to do.

So looking at inline oop JNIHandles::resolve(jobject handle) in jniHandles.hpp, the first line translates to

oop p = (handle == NULL ? (oop)NULL : *(oop*)handle);

The second line is casting the address to the proper pointer type and writing the value, so index_oop_from_field_offset_long(p,offset) must be what produces the address. This one translates to

if (sizeof(char*) == sizeof(jint))    // (this constant folds!)
    return (address)p + (jint) byte_offset;
else
    return (address)p +        byte_offset;

where byte_offset == offset.

Combining the two, I believe this is the way to get the proper address (which I will have to cast to the proper type when reading/writing):

inline void* get_addr(jobject base, jlong offset){
    oop p = (base == NULL ? (oop)NULL : *(oop*)base);
    if (sizeof(char*) == sizeof(jint))
        return (address)p + (jint) offset;
    else
        return (address)p +        offset;

}

Great, now all I need to know is how to choose oop and address s.t. the address is properly created.

I don't necessarily need to care about what they are, exactly, I just need to do a

using oop = SOMETHING_MATCHING_OOP_IN_SIZE;
using address = SOMETHING_ELSE_THAT_MATCHES_ADDRESS;

But what? I've flipped through the files until I grew tired of missing what I'm looking for and downloaded the hotspot source files (links at the bottom of the navigation on the left side).

grep -r "typedef .* oop" .

executed from within the src folder reveals

./share/vm/memory/classify.hpp:typedef enum oop_type {
./share/vm/oops/oopsHierarchy.hpp:typedef juint narrowOop; // Offset instead of address for an oop within a java object
./share/vm/oops/oopsHierarchy.hpp:typedef class klassOopDesc* wideKlassOop; // to keep SA happy and unhandled oop
./share/vm/oops/oopsHierarchy.hpp:typedef class oopDesc*    oop;

so grep -r ".*class oopDesc.*" .

gives me

./share/vm/gc_implementation/parallelScavenge/parMarkBitMap.hpp:class oopDesc;
./share/vm/interpreter/bytecodeInterpreter.hpp:    class oopDesc*   r;
./share/vm/memory/universe.hpp:  friend class oopDesc;
./share/vm/oops/oop.hpp:class oopDesc {
./share/vm/oops/oopsHierarchy.hpp:typedef class oopDesc*    oop;

Opening oop.hpp, we find a 353 line class definition that I have no idea yet how to translate into a useful figure -- especially since at least on of the fields may or may not be there, depending on an #ifndef

There HAS to be an easier way to go about this. But I don't immediately see how. Any suggestions?

来源:https://stackoverflow.com/questions/47267806/substituting-jvm-oop-pointer-in-c

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!