【问题标题】:JNI passing a long value to a native methodJNI 将 long 值传递给本地方法
【发布时间】:2017-03-10 15:09:14
【问题描述】:

如上所述,我试图在 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类中native函数的声明:

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 值吗?

【问题讨论】:

  • 我无法重现。你能发个minimal reproducible example吗?
  • 为什么Java方法有2个参数,C函数有1个?
  • @JornVernee ,我已经编辑了我的帖子,希望我的问题现在会变得更清楚。
  • @user2543253 ,忘了重构我的代码,但现在我做对了,编辑了代码。

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


【解决方案1】:

我似乎已经弄清楚了问题所在。当你有一个 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方法的签名。

【讨论】:

    猜你喜欢
    • 2011-10-02
    • 2012-11-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-12-07
    • 1970-01-01
    相关资源
    最近更新 更多