JNA 是不是释放 Go CString 返回值的内存
Posted
技术标签:
【中文标题】JNA 是不是释放 Go CString 返回值的内存【英文标题】:Does JNA free memory of Go CString return valueJNA 是否释放 Go CString 返回值的内存 【发布时间】:2019-11-08 02:02:42 【问题描述】:我有一个这样的 JNA 接口:
interface JJ
String Hello(GoString.ByValue sql);
Go 中对应的原生代码:
//export Hello
func Hello(ss string) *C.char
s := ss + " world"
return C.CString(s)
本机代码返回一个指向字符串的指针。
JNA 代码是否释放本地代码分配的字符串指针? 如果没有,如何释放?
【问题讨论】:
【参考方案1】:我将回答一般性问题和具体示例。
JNA 不会维护对本机内存的任何引用,除非您自己在 JNA 中分配它(例如,定义一个 byte[]
数组或 Memory
缓冲区,然后将其传递给函数)。在这些情况下,当 Java 对象被垃圾回收时,本机内存会被释放。
如果您没有将任何内存传递给 C 来填充,那么 JNA 不会对本机内存做任何事情,您必须阅读 API 文档以了解您对释放本机字符串的责任.
C++ CString 类型不一定需要被释放unless it is stored in a new object。然而,Go 确实将CString
实现为一个对象,并记录了这些要求。对于您的特定示例,the docs 说:
Go 的内存不知道 C 代码分配的内存 经理。当您使用 C.CString(或任何 C 内存)创建 C 字符串时 分配)你必须记住在完成后释放内存 通过调用 C.free.
来自cgo wiki:
要记住的重要一点是 C.CString() 将分配一个 适当长度的新字符串,并将其返回。这意味着 C 字符串不会被垃圾收集,这取决于您 释放它。以下是执行此操作的标准方法。
// #include <stdlib.h>
import "C"
import "unsafe"
...
var cmsg *C.char = C.CString("hi")
defer C.free(unsafe.Pointer(cmsg))
// do something with the C string
当然,你不需要使用 defer 来调用 C.free()。你可以 随时释放 C 字符串,但您有责任 确保它发生。
【讨论】:
as docs 说 CString 复制并分配了一个需要显式释放的新字符串,因此实际上它没有分配在堆栈上 @pdeva 谢谢,我已经更新了我的答案。我不知道这是否是 Go 的特点。我的回答基于this answer。可能是 Go 内部调用了new
变体。【参考方案2】:
让 Java 分配缓冲区,以便它会为您释放它。否则您必须自己释放它并导出释放函数..
public interface JJ
JJ lib = (JJ)Native.loadLibrary("jj.so", JJ.class);
void Hello(byte[] sql);
func Hello(ss []byte)
copy(ss[:], string(ss) + " world")
用法:
void main(String[] args)
byte[] text = new byte[256];
JJ.lib.Hello(text);
System.out.println(Native.toString(text));
您可以将整个内容包装到一个通用函数中,该函数将为您为任何给定的本机函数创建一个字符串。但您明白了。
-
Java 分配缓冲区,Go-Lang 填充它,Java 自动释放它。
Go-Lang 分配缓冲区,Java 使用它,Go-Lang 释放它。
在这两种情况下,分配缓冲区的人都必须释放它。
【讨论】:
以上是关于JNA 是不是释放 Go CString 返回值的内存的主要内容,如果未能解决你的问题,请参考以下文章