JNI 将 long 值传递给本地方法
JNI passing a long value to a native method
所以如上所述,我试图在 Unsafe 的帮助下将一个 int 对象复制到堆外内存中。这是我的主要功能:
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 agent中定义的函数。这是 java class:
中本机函数的声明
private static native void getCopiedObject(long address);
这里是agent.h中函数的声明:
JNIEXPORT void JNICALL Java_main_Main_getCopiedObject(JNIEnv *, jlong);
这就是我遇到麻烦的地方...我在 C++ 函数中获得的 long 值与我传入的值不同 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 位,所以我在我的 C++ 代码中使用 long long
...我尝试了有符号和无符号的转换,但它从来没有奏效...
所以当我 运行 这段代码时,我得到以下输出:
JAVA:
COPIED TO ADDRESS: 1487190592
AGENT:
UNSIGNED LONG LONG 37025744
SIGNED LONG LONG 37025744
根据输出,我以错误的方式将 jlong 转换为 long...
有人知道如何从 jlong
中获取正确的 long long
值吗?
我好像明白问题出在哪里了。当你有一个 static native
方法时,除了你在 Java 中的参数之外,还有 2 个额外的参数。第一个是 JNIEnv
,第二个是 jclass
.
我不知道您是如何生成 .h
文件的,但是当我使用时:
javah -jni Main
我得到签名:
JNIEXPORT void JNICALL Java_Main_passLong(JNIEnv *, jclass, jlong);
在 .h
文件中。如果我这样使用它,它会按预期运行。所以我的解决方案是在 jlong
.
之前添加一个 jclass
参数
如果删除 jclass
参数,我会看到错误的值。我猜JVM在加载库的时候没有检查native方法的签名。
所以如上所述,我试图在 Unsafe 的帮助下将一个 int 对象复制到堆外内存中。这是我的主要功能:
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 agent中定义的函数。这是 java class:
中本机函数的声明private static native void getCopiedObject(long address);
这里是agent.h中函数的声明:
JNIEXPORT void JNICALL Java_main_Main_getCopiedObject(JNIEnv *, jlong);
这就是我遇到麻烦的地方...我在 C++ 函数中获得的 long 值与我传入的值不同 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 位,所以我在我的 C++ 代码中使用 long long
...我尝试了有符号和无符号的转换,但它从来没有奏效...
所以当我 运行 这段代码时,我得到以下输出:
JAVA:
COPIED TO ADDRESS: 1487190592
AGENT:
UNSIGNED LONG LONG 37025744
SIGNED LONG LONG 37025744
根据输出,我以错误的方式将 jlong 转换为 long...
有人知道如何从 jlong
中获取正确的 long long
值吗?
我好像明白问题出在哪里了。当你有一个 static native
方法时,除了你在 Java 中的参数之外,还有 2 个额外的参数。第一个是 JNIEnv
,第二个是 jclass
.
我不知道您是如何生成 .h
文件的,但是当我使用时:
javah -jni Main
我得到签名:
JNIEXPORT void JNICALL Java_Main_passLong(JNIEnv *, jclass, jlong);
在 .h
文件中。如果我这样使用它,它会按预期运行。所以我的解决方案是在 jlong
.
jclass
参数
如果删除 jclass
参数,我会看到错误的值。我猜JVM在加载库的时候没有检查native方法的签名。