【问题标题】:JNI: properly manage lifetime of a Java objectJNI:正确管理 Java 对象的生命周期
【发布时间】:2012-10-14 00:25:14
【问题描述】:

当我在 c++ 中创建本机实现对等体时,如何确保在 JVM 删除 java 对象时也删除本机部分?我可以添加一些java对象的用户必须显式调用的方法,但我想知道当java对象被删除(垃圾收集)时是否有一些我可以处理的钩子,以便我可以自动删除c++实现对象也是。

我查看了JACE,它似乎可以做到这一点,但我需要运行 PeerEnhancer 来修补生成的类文件(可能这就是它挂钩删除的方式?或者它可能需要这个修补来做其他事情)。但是,我想避免弄乱已编译的 java 文件,我不想要任何花哨的东西

【问题讨论】:

    标签: android c++ android-ndk java-native-interface


    【解决方案1】:

    请注意,通过采用终结器,您会在最糟糕的地方逗弄 JVM。在 finalizer() 中调用 JNI 就像在驾驶时调整发动机气门正时。虽然在技术上是可行的,但也很容易导致 JVM 泄漏或崩溃。即使是最轻微的多线程接触,您肯定会在某些时候死锁/崩溃。如果您说“我不想要任何花哨的东西”,我建议您使用显式调用的方法。是的,按照惯例要求一定的方法顺序是肮脏的设计,但是 JNI 通常是肮脏的。

    如果一个受人尊敬的 JNI 库做了一个隐藏的类检测而不是简单地使用终结器,它也许是有原因的。一些推荐阅读(甚至没有提到 JNI!):

    http://asserttrue.blogspot.com/2008/11/finalization-is-evil.html

    http://elliottback.com/wp/java-memory-leaks-w-finalize-examples/

    我的建议是:是的,使用虚拟方法 detachFromPeer() 实现一个基类,在其中设置一些“分离”标志,然后在终结器中检查该标志并发出一些警告。

    【讨论】:

    • 我知道 GC 问题。代码显然需要手动清理,但同时我的代码想知道 GC 何时删除了对象。
    • 那么,你想知道 GC 什么时候删除了对象,或者更确切地说,当程序代码、算法决定不再需要该对象时?后者是确定性和可管理的。相反,你无法知道 GC 何时决定调用终结器(如果有的话)。
    • 对不起,问题的标题可能具有误导性。我只想知道当 GC 实际丢弃对象时如何挂钩该事件,而不是何时/为什么/如何。我无意依赖那个钩子,我主要需要它来进行调试(例如,断言已经执行了手动清理等)。
    • 不是问题的标题,那么问题本身就具有误导性。您明确要求 “删除 java 对象时,我可以自动删除 c++ 对象”。这听起来很像依赖 GC 终结器钩子。无论如何,我很高兴调试/断言手动清理是您在终结器中最想做的事情。您为自己节省了一些严重的未来痛苦。
    • 这里有一些 FUD。终结器在单个线程上调用,因此除非它们自己启动线程,否则肯定不会出现死锁问题。
    【解决方案2】:

    这种情况很少见,您应该真正使用终结器,但您也应该让您的 Java 类也可关闭。

    【讨论】:

    • 我不是 Java 专家,我会把它传给我的 Java 伙伴 :) 是否可以将样板代码放在某个基类中,以便所有需要本地对等点的 Java 类都需要从自动处理这些东西的类继承(例如,从 java 析构函数/终结器调用 virtual detachFromPeer() 以确保 c++ 对象不会无缘无故地悬空)。
    猜你喜欢
    • 2012-12-28
    • 1970-01-01
    • 2013-08-08
    • 1970-01-01
    • 2012-12-17
    • 1970-01-01
    • 2012-11-06
    • 2020-07-28
    • 1970-01-01
    相关资源
    最近更新 更多