【问题标题】:Calling a Java variadic function from C through the JNI通过 JNI 从 C 调用 Java 可变参数函数
【发布时间】:2022-01-24 00:15:22
【问题描述】:

我目前正在为我从事的 C 库创建一些 Java 绑定。我们的 C 结构之一有一个字符缓冲区,它是一个文件系统路径。调用 C 函数后,缓冲区被正确填充。我想获取缓冲区并将其转换为 Java 对象上的 java.nio.file.Path 成员。

但是我遇到了一些麻烦。由于某种原因,我在 C 中生成了一个NullPointerException,但我看不出问题所在。

创建java.nio.file.Path对象的方式是通过java.nio.file.Paths::get()

下面是相关的C代码:

const jclass paths_class = (*env)->FindClass(env, "java/nio/file/Paths");
if ((*env)->ExceptionCheck(env))
    return;
const jmethodID get_method = (*env)->GetStaticMethodID(
    env, paths_class, "get", "(Ljava/lang/String;[Ljava/lang/String;)Ljava/nio/file/Path;");
if ((*env)->ExceptionCheck(env))
    return;
const jstring path_str = (*env)->NewStringUTF(env, info.mi_path);
if ((*env)->ExceptionCheck(env))
    return;
const jobject path_obj =
   (*env)->CallStaticObjectMethod(env, paths_class, get_method, path_str); // exception generated here
if ((*env)->ExceptionCheck(env))
    return;

还有 Java 类:

public final class MclassInfo {
    private native void _get(final Kvdb kvdb, Mclass mclass) throws HseException;

    private long allocatedBytes;
    private long usedBytes;
    private Path path;

    MclassInfo(final Kvdb kvdb, final Mclass mclass) throws HseException {
        _get(kvdb, mclass);
    }

    public long getAllocatedBytes() {
        return allocatedBytes;
    }

    public long getUsedBytes() {
        return usedBytes;
    }

    public Path getPath() {
        return path;
    }
}

我能想到的只是我没有正确调用 Java 可变参数函数。我也尝试将NULL 作为方法调用的额外参数传递,但最终遇到了同样的问题。

【问题讨论】:

  • 你有堆栈跟踪吗?哪个语句导致 NPE?当您单步执行代码时,您的 IDE 会向您显示什么?
  • Jim,对于通过 Maven 运行测试并通过 gdb 连接到进程的这种特定情况,很难获得堆栈跟踪。我需要继续努力。您可能拥有的任何资源也将是有价值的。但与此同时,我会尝试答案的建议。

标签: java c java-native-interface


【解决方案1】:

您尝试调用的方法声明为get(String first, String... more)。 Java 中的可变参数语法只是指定类型数组的糖,即此方法的 两个 参数实际上是 StringString[] - 您在 GetStaticMethodID 中正确编码调用为(Ljava/lang/String;[Ljava/lang/String;)

所以要调用它你需要两个参数:一个String和一个String[](数组)——并且(对于你的情况)数组必须包含零个元素,但这样的空数组与 NULL 相同。看看NewObjectArray

【讨论】:

  • 哇。这绝对是解决办法。我想我不清楚的是零元素数组与 NULL 不同。我曾考虑过尝试它,但又反对它,因为我需要创建一个零元素数组似乎很奇怪。回想起来,我应该试一试。非常感谢您的帮助。
  • @tristan957 零元素数组需要保护用户免受空指针异常的影响。取消引用零元素数组是无操作的,但取消引用 Null 指针是未定义的行为异常。
猜你喜欢
  • 2023-04-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-01-30
  • 1970-01-01
  • 2012-07-04
  • 1970-01-01
相关资源
最近更新 更多