【问题标题】:JNA memory clean upJNA 内存清理
【发布时间】:2021-11-24 20:27:37
【问题描述】:

根据 JNA 的 Memory 类文档,当需要释放不再引用的内存时,需要调用 finalize() 方法。但是在JNA example 中,提到了内存对象在超出范围时被释放。

// note: like Memory, StringArray will free the contiguous block of memory it copied the Strings into when the instance goes out of scope

问题是:

  • 这是否意味着,当 Memory 类对象超出范围并释放底层本机内存时,它在内部调用 finalize()?

  • StringArray 类和 Memory 类在行为 w.r.t 上是相同的。内存管理?以及如何?

【问题讨论】:

    标签: java memory-management memory-leaks native jna


    【解决方案1】:

    JNA 的 Memory 实现依赖于 Java 垃圾回收 (GC)。 Java 没有显式获取对象内存的函数,保存对象数据所需的内存由 VM 管理,在实例化对象时分配。

    GC 是一个进程,它释放所有不再引用的内存。 Java 中的所有类都可以声明一个方法finalize,当该类的对象即将被清除时,GC 将调用该方法,并为对象提供进行一些最终清理工作的选项。在 JNA 的情况下,此清理将释放本机内存,该内存分配在 GC 控制区域之外。

    需要注意的是,使用 finalize 已被弃用,不应再使用,但切换到替代方法也意味着引入略有不同的行为,这是 JNA 仍然依赖 GC 进行清理的原因之一.

    【讨论】:

      【解决方案2】:

      针对Matthias Bläsing's answer提出的具体问题,我想补充几点:

      • 一般不直接拨打finalize()。它被 JVM 作为垃圾收集过程的一部分调用。
      • Memory 中,finalize() 方法只调用dispose() 方法。如果您真的想立即摆脱内存,这将是首选的调用方法。但是dispose()protected,所以如果您真的觉得需要清理本机内存分配,则需要扩展Memory 以利用此方法。
        • 您可能会考虑一个这样的子类,它扩展了Closeable,其中close() 方法实现从超类调用dispose()。然后,例如,您可以使用 try with resources 块,并在块的末尾清理本机内存(资源)。当然,在 GC 之前,Java 对象仍然存在。
        • 但是请注意,释放本机内存会带来处理成本,除非您的内存真的很短缺,否则它不会获得太多收益,因为在对象被 GC 之前,您仍然拥有与对象关联的 Java 堆内存。如果你的内存那么短,并且去那个级别的细节来控制本机分配清理的时间,你可能想直接去malloc()free()调用自己并在更高级别控制它,也许回收/重复使用它...

      您还询问了StringArray,但与Memory 更接近的是作为数组成员的NativeString 对象。事实上,它们的内部实现是一个StringMemory 对象,它扩展了Memory,所以它的行为是相同的;也就是说,free() 本机内存 via dispose() via finalize() NativeString 是 JVM 收集的垃圾。

      【讨论】:

      • 感谢 Daniel 详细阐述了 Matthias 的答案并解释了 StringArray。
      • 所以@Daniel 是不是意味着,JNA 每次都借助 GC 来清理超出 JVM 控制区域的本机内存 [不包括 malloc 和免费 API]?
      • @Prashant 是的,但有一个例外。 Memory 有一个 disposeAll() 方法,可以主动释放所有分配的内存。当然,它很慢。但有效。
      猜你喜欢
      • 1970-01-01
      • 2014-03-21
      • 1970-01-01
      • 2022-08-04
      • 1970-01-01
      • 2014-07-18
      • 2021-07-13
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多