是否执行GoNAString返回值的JNA空闲内存

问题描述 投票:0回答:2

我有这样的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代码是否释放本机代码分配的字符串的指针?如果没有,如何释放它?

java jna cgo
2个回答
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字符串,但这是您的责任确保它发生。


0
投票

让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));
}

您可以将整个内容包装到一个泛型函数中,该泛型函数将为任何给定的本机函数为您创建一个字符串。但是您明白了。

  1. Java分配缓冲区,Go-Lang填充它,Java自动分配它。
  2. Go-Lang分配缓冲区,Java使用它,Go-Lang释放它。

在两种情况下,分配缓冲区的人都必须释放它。

© www.soinside.com 2019 - 2024. All rights reserved.