是否可以让 GC 管理本机对象的生命周期?

2023-12-19

凭借 C++ 和 C# 经验以及一些 Java 知识,我现在正在启动一个 Java+JNI (C++) 项目(Android,如果这很重要的话)。

我有一个本机方法,它创建一些 C++ 类并返回一个指向它的指针作为 Java 长值(例如句柄)。然后从 Java 代码各处调用其他本机方法,使用句柄作为参数对此类执行一些本机操作。 C++ 端不拥有该对象,而 Java 端拥有该对象。但在当前的架构设计中,很难定义谁到底拥有该对象以及何时删除它。因此,让 Java VM 垃圾收集器以某种方式管理对象的生命周期可能会很好。 C++类不消耗任何资源,除了一些不大的内存。因此,如果多个这样的对象不会被破坏,那就没问题了。

在 C# 中,我可能会将本机 IntPtr 句柄包装在某些托管包装类中。当托管包装器被垃圾收集时,重写它的终结器以调用本机对象的析构函数。 SafeHandle、AddMemoryPressure 等在这里也可能有帮助。

这与 Java 的 Finalize 是不同的故事。在 Java 中的“Hello world”之后您知道的第二件事是,使用 Finalize 是不好的。在 Java 中还有其他方法可以实现这一点吗?也许使用 PhantomReference?


好吧,让我们考虑一下为什么 Finalize 和 Co 有问题的原因:如您所知,不能保证在 VM 关闭之前调用 Finalize,这意味着特殊的清理代码不一定会运行(在我看来这是一个错误的决定,我不认为在清理时没有看到任何运行最终队列的问题,但事实就是这样)。这与 C# 中的情况完全相同

现在你的对象只消耗内存,当虚拟机被销毁时,内存将被操作系统清理,所以最终确定有问题的唯一情况对你来说并不重要。所以,是的,你确实可以使用这个变体,它会工作得很好,但它可能不完全被认为是一个伟大的架构设计 - 一旦你向你的 C++ 代码添加资源,而操作系统无法正确处理清理,你会遇到问题

另请注意,实现终结器会导致 GC 产生一些额外的开销,并且意味着需要两个周期来清理这些对象之一(无论您做什么,都不要在 Finalize 方法中保存对象)

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

是否可以让 GC 管理本机对象的生命周期? 的相关文章

随机推荐