【问题标题】: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 代码是否释放本地代码分配的字符串指针? 如果没有,如何释放?

【问题讨论】:

    标签: java jna cgo


    【解决方案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));
    }
    

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

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-01-26
      • 1970-01-01
      • 2021-05-23
      • 1970-01-01
      • 2017-07-27
      • 1970-01-01
      • 2011-01-04
      • 1970-01-01
      相关资源
      最近更新 更多