【问题标题】:Is there a memory leak issue with using JNA's Memory class?使用 JNA 的 Memory 类是否存在内存泄漏问题?
【发布时间】:2016-01-23 06:48:14
【问题描述】:

我想通过 JNA 将 byte[] 传递给本机方法。我发现的所有关于这类事情的示例要么使用Memory 实例,要么使用直接分配的ByteBuffer,然后从中获取Pointer

但是,当我阅读文档时,他们说底层的本机内存——据我所知,它是“从书本上”分配的 在 JVM 管理的堆之外——这些 Java 对象消耗只有当对象的finalize() 方法被调用时才会被释放。

但是何时调用终结器与对象何时超出范围无关。在垃圾收集器真正完成它们之前,它们可能会徘徊很长时间。因此,它们分配的任何本机内存在超出范围后将保持分配任意长的时间。如果他们持有大量内存和/或如果有很多对象,那么在我看来你有一个有效的内存泄漏。或者至少会有一个稳态内存消耗可能比它看起来需要的高很多。换句话说,与JNA/ByteBuffer not getting freed and causing C heap to run out of memory中描述的行为类似

JNA 有没有办法解决这个问题?或者我是否需要为此放弃 JNA 并改用 JNI,以便我可以使用 JNIEnv::GetByteArrayElements(),这样就不需要任何可以持续任意长时间的“书外”内存分配?子类Memory 是否可以接受以访问dispose() 方法并使用它来释放我的时间轴上的底层本机内存而不是GC 的时间轴?或者当终结器运行时会导致问题?

【问题讨论】:

  • 我不会担心 - 每当堆满并尝试分配更多内存时都会调用垃圾收集器,因此它只在需要时运行。
  • 问题,据我了解,这类对象占用最少的 GC 托管堆空间,但会占用更多非托管 process 内存空间。因此,在 GC 看到足够的堆“压力”来完成任务之前,process 可能会占用大量内存。请参阅我在主要问题描述中添加的链接。
  • 啊是的..根据您链接的页面上的链接,它是known bug,自 2001 年以来打开,仍未解决。我想您的问题的简短回答是“是”。最后一个建议:如果malloc 失败,您可以从本机代码中调用它,而不是像解决方法中建议的那样定期调用System.gc()

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


【解决方案1】:

JNA 提供了Memory.disposeAll()Memory.dispose() 来显式释放内存(后者要求您继承Memory),因此如果您确实遇到内存压力,而常规 GC 是不够的,你有一些额外的控制可用。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-07-28
    相关资源
    最近更新 更多