JNI将long值传递给本机方法

时间:2017-03-10 15:09:15

标签: java c++ java-native-interface javaagents jvmti

如上所述,我试图在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代理中定义的函数。以下是java类中本机函数的声明:

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 ...

有人知道如何从long long获取正确的jlong值吗?

1 个答案:

答案 0 :(得分:3)

我似乎已经弄明白问题是什么。当你有一个static native方法时,除了Java中的那个之外还有2个额外的参数。第一个是JNIEnv,第二个是jclass

我不知道你是如何生成.h文件的,但是当我使用时:

javah -jni Main

我收到了签名:

JNIEXPORT void JNICALL Java_Main_passLong(JNIEnv *, jclass, jlong);

.h文件中。如果我像这样使用它,它的行为与预期的一样。所以我的解决方案是在jclass之前添加jlong参数。

如果删除jclass参数,我会看到错误的值。我想JVM在加载库时不会检查本机方法的签名。