我有这样的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代码是否释放本机代码分配的字符串的指针?如果没有,如何释放它?
我将回答一般性问题和具体示例。
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字符串,但这是您的责任确保它发生。
让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));
}
您可以将整个内容包装到一个泛型函数中,该泛型函数将为任何给定的本机函数为您创建一个字符串。但是您明白了。
在两种情况下,分配缓冲区的人都必须释放它。