使用 JNA 时,如果我通过调用 Java 方法回调收到 char* 值,如何释放它?

When using JNA, if I receive a char* value through calling a Java method callback, how can I free it?

提问人:healthsgood 提问时间:5/9/2023 最后编辑:healthsgood 更新时间:5/9/2023 访问量:52

问:

本机代码如下所示:

typedef char *(*getJavaString)();

getJavaString getJavaStringFunc = nullptr;

void registerGetJavaStringFunc(getJavaString func) {
    getJavaStringFunc = func;
}

void someCContextFunc() {
    char* value = getJavaStringFunc();
    // How do I free the value? Can I use `free(value)` directly?
}

我首先在 Java 中调用 registerGetJavaStringFunc 以向 C 注册 Java 函数。将来,我将调用 getJavaStringFunc 函数来获取 C 上下文中的值。但是,如何释放该值?

我最初编写代码是为了直接释放“值”,如下所示:

char* value = getJavaStringFunc();
free(value);

这种方法似乎工作得很好。然而,在咨询 ChatGPT 时,我被告知可能涉及潜在风险。ChatGPT 建议我在 C 上下文中注册一个名为“freeJnaValue”的新函数,并使用该函数来释放“value”。在这一点上,我不确定哪种方法更合适,以及我的下一步应该是什么。

c 内存泄漏回 java-native-interface jna

评论

3赞 John Bollinger 5/9/2023
我不考虑 ChatGPT 对任何技术问题的回答。
0赞 user253751 5/9/2023
是JNI还是JNA?看起来像JNA,对吧?
0赞 Andrew Henle 5/10/2023
@JohnBollinger 你对 ChatGPT 的不尊重仅限于技术问题?鉴于 GhatGPT 在技术问题上是多么明显错误,并且没有证据表明无能仅限于技术问题,......

答:

1赞 John Bollinger 5/9/2023 #1

在咨询 ChatGPT 后,

那是个错误。ChatGPT 通常会发出听起来不错的答案,但它在写出技术问题的正确答案方面非常糟糕。这是最糟糕的结果:由于答案的形式,你可能倾向于相信它,但要评估它的正确性,你需要知道足够多的东西,以至于你一开始就不需要问ChatGPT。

我被告知可能涉及潜在风险。

ChatGPT 是用这些术语说的吗?这将是误导性的。将指针传递给不仅有风险,而且是错误的free

ChatGPT 建议我在 C 上下文中注册一个名为“freeJnaValue”的新函数,并使用该函数来释放“value”。

这是荒谬的。名称“freeJnaValue”没有特殊意义,如果可以释放回调提供的对象,那么直接在从回调接收它的函数中执行此操作就可以了。为此目的插入另一个函数并没有什么特别的好处。

JNA API 文档

如果回调返回 or ,则返回的内存将一直有效,直到返回的对象被 GC'd 捕获。StringString[]

这告诉您,返回给回调调用方的映射 C 字符串由 Java 管理你根本不应该自己释放它。

顺便说一句,因为它映射到 a 并且 s 是不可变的,所以您不应该依赖能够修改它。那么,最好在 C 端声明它返回,而不仅仅是 .StringStringconst char *char *

评论

0赞 user253751 5/9/2023
以及应该如何防止字符串被 GC'd?
0赞 John Bollinger 5/9/2023
@user253751,这是一个完全不同的问题。如果你想要的东西不仅仅是标准的“确保它仍然可以从实时 Java 线程访问”,那么它应该作为它自己的问题提出。
0赞 healthsgood 5/10/2023
如果回调返回一个对象,而不是 string 或 string[],则返回的内存将一直有效,直到返回的对象被 GC'd?
0赞 healthsgood 5/10/2023
GC何时发生?返回的 char* 在 jvm 中是否有本地引用?
0赞 John Bollinger 5/10/2023
@healthsgood,有关处理引用类型为 和 以外的 Java 返回值的文档是稀疏的。我发现似乎没有一个可以解决返回结构或联合指针指向的对象的生存期问题,但一个合理的猜测是,它类似于为返回的 s 和 s 定义的行为。StringString[]StringString[]