Поэтому я решил, что «самый простой» способ ответить мой другой вопрос стоит «просто» взглянуть на реализацию небезопасного в C / C ++.
(
В двух словах, у меня есть Object base
и long offset
в Java, что я перехожу к C / C ++ с помощью собственного интерфейса Java (JNI), откуда я хочу выполнить эквивалент C / C ++
unsafe.setInt(base,offset,1)
)
Такая реализация предоставляется, например, OpenJDK: unsafe.cpp
Меня больше не волнует, что там, я просто хочу получить прямой доступ к ценностям.
Итак, глядя на реализацию, я вижу
#define SET_FIELD(obj, offset, type_name, x) \
oop p = JNIHandles::resolve(obj); \
*(type_name*)index_oop_from_field_offset_long(p, offset) = x
Что, я надеюсь, делает то, что я ожидаю.
Итак, глядя на inline oop JNIHandles::resolve(jobject handle)
в jniHandles.hpp, первая строка переводится как
oop p = (handle == NULL ? (oop)NULL : *(oop*)handle);
Вторая строка — приведение адреса к правильному типу указателя и запись значения, поэтому index_oop_from_field_offset_long(p,offset)
должно быть то, что производит адрес. Этот переводится как
if (sizeof(char*) == sizeof(jint)) // (this constant folds!)
return (address)p + (jint) byte_offset;
else
return (address)p + byte_offset;
где byte_offset == offset
,
Объединяя их, я считаю, что это способ получить правильный адрес (который мне придется приводить к нужному типу при чтении / записи):
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;
}
Отлично, теперь все, что мне нужно знать, это как выбрать oop
а также address
S.T. адрес правильно создан.
Мне не обязательно заботиться о том, что они есть, мне просто нужно сделать
using oop = SOMETHING_MATCHING_OOP_IN_SIZE;
using address = SOMETHING_ELSE_THAT_MATCHES_ADDRESS;
Но что? Я пролистал файлы, пока не устал от того, что пропустил то, что ищу, и скачал исходные файлы горячей точки (ссылки внизу навигации слева).
grep -r "typedef .* oop" .
выполнено изнутри src
папка показывает
./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;
так grep -r ".*class oopDesc.*" .
дает мне
./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;
открытие oop.hpp, мы нашли определение класса из 353 строк, которое я пока не знаю, как перевести на полезную фигуру, тем более, что, по крайней мере, одно из полей может быть или не быть там, в зависимости от #ifndef
Должен быть более простой способ сделать это. Но я не сразу вижу, как. Какие-либо предложения?
Задача ещё не решена.
Других решений пока нет …