【问题标题】:Freeing Natives Objects [closed]释放 Natives 对象 [关闭]
【发布时间】:2013-10-31 20:18:47
【问题描述】:

如何检测Java对象的GC调用的最佳方法?

我正在为 C++ 代码构建 Java Wrapper,每次调用 GC 时我都需要释放在 C++ 代码中分配的内存

我看到了一些解决方案,但没有一个让我满意。

其中一个是:

Object obj = null;
try{
    obj = new Object();
    // do things
} finally {
   if(obj != null){
      obj.freeCObjects();
   }
}

【问题讨论】:

  • 每次调用 GC 时我都需要释放内存这不是 GC 已经在做的吗?
  • @SotiriosDelimanolis 我说的是从 C++ 包装器对象中释放内存。
  • 其他解决方案有什么问题?您希望得到什么样的改进?
  • JDK 没有提供到 GC 的钩子。
  • @Keppil 我想讨论所有人的好处并了解其他解决方案。我正在构建一个 API,所以我想为我的解决方案选择最佳方式。

标签: java c++ memory java-native-interface wrapper


【解决方案1】:

您可能需要考虑java.lang.Object 上可用的finalize() 方法。

It is called by the garbage collector on an object when garbage collection determines 
that there are no more references to the object.

一般来说,最好避免使用终结器,因为 JVM 不保证在任何对象上都会调用 finalize(),但是当需要清理本机(通常是非 Java)资源时,终结器很有用。

这是一个简单的例子:

    Object obj = new Object() {
        @Override
        protected void finalize() throws Throwable {
            System.out.println("finalize object");
            super.finalize();
        }
    };

终结器可能被垃圾回收调用。

【讨论】:

    【解决方案2】:

    仅使用垃圾收集器没有可靠的方法来做到这一点。通常的方法(例如,由使用本机组件的 SWT UI 工具包采用)是要求客户端在对象上调用 disposedestroy 方法。

    【讨论】:

    • 这是一个好方法。我已经在这样做了。但是没有其他解决办法吗?
    • @Victor 没有其他可靠的解决方案,没有。终结器不能保证永远运行,即使它们确实运行,JVM 也可能在很长一段时间内无法处理它们,特别是如果 JVM 没有看到对象使用了太多 Java 堆空间(因为它们'主要在其他地址空间中)。此外,虽然在终结器中提供“救援”关闭操作很好,但在文档中指出这一点将不可避免地导致懒惰的程序员无法正确关闭资源并遇到麻烦。
    【解决方案3】:

    您不太可能希望每次运行 GC 时都释放内存。在运行 GC 时,您必须更有可能将内存释放给未使用的对象。

    您可以通过提供一个包装器来实现这一点,该包装器具有用于释放资源的 finalize() 的实现。当包装器被丢弃时,您可以清理资源。如果你真的希望它在每次 GC 上消失,你可以持有一个对包装器的 WeakReference。

    顺便说一句,OpenJDK/Oracle HotSpot JVM 有另一种更轻量级的资源释放机制。这涉及使用未添加到终结队列中的 Cleaner 对象(意味着可以更快地释放它)参见具有 Cleaner 的直接 ByteBuffer 作为示例。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-08-27
      • 1970-01-01
      • 1970-01-01
      • 2017-02-08
      相关资源
      最近更新 更多