Итак, как описано выше, я пытаюсь скопировать объект int в память вне кучи с помощью Unsafe. Вот моя основная функция:
public static void main(String[] args) throws Exception {
UnsafeHelper hlpr = new UnsafeHelper();
int original = 100;
long copyaddress = hlpr.shallowCopy(original);
System.out.println("COPIED TO ADDRESS: " + copyaddress);
int copy = (int) hlpr.fromAddress(copyaddress);
getCopiedObject(copyaddress);
}
он дает мне адрес начала скопированного объекта (copyaddress
).
Далее я хочу передать этот адрес функции, определенной в агенте jni. Вот объявление нативной функции в классе Java:
private static native void getCopiedObject(long address);
Вот объявление функции в agent.h:
JNIEXPORT void JNICALL Java_main_Main_getCopiedObject(JNIEnv *, jlong);
И вот тут я попадаю в беду … Длинное значение, которое я получаю в функции C ++, отличается от того, которое я передаю в Java …
JNIEXPORT void JNICALL Java_main_Main_getCopiedObject(JNIEnv *env, jlong address){
...
unsigned long long a = address;
signed long long b = address;
printf("UNSIGNED LONG LONG %llu \n", a);
printf("SIGNED LONG LONG %lld \n", b);
...
}
В моем случае размер Java Long составляет 64 бита, поэтому я использую long long
в моем коде c ++ … я пробовал и подписанные и неподписанные преобразования, но это никогда не работало …
Поэтому, когда я запускаю этот код, я получаю следующие выводы:
JAVA:
COPIED TO ADDRESS: 1487190592
AGENT:
UNSIGNED LONG LONG 37025744
SIGNED LONG LONG 37025744
Согласно выводу, я неправильно конвертирую jlong в long …
Кто-нибудь знает, как получить правильный long long
значение из jlong
?
Кажется, я понял, в чем проблема. Когда у вас есть static native
В методе есть 2 дополнительных аргумента, помимо того, что есть в Java. Во-первых, это JNIEnv
а второй jclass
,
Я не знаю, как именно вы создали свой .h
файл, но когда я использую:
javah -jni Main
Я получаю подпись:
JNIEXPORT void JNICALL Java_Main_passLong(JNIEnv *, jclass, jlong);
в .h
файл. Если я использую его таким образом, он ведет себя как ожидалось. Поэтому мое решение было бы добавить jclass
параметр перед jlong
,
Если я удалю jclass
Параметр, я вижу неправильное значение. Я предполагаю, что JVM не проверяет подпись нативного метода при загрузке библиотеки.
Других решений пока нет …