0

在这种情况下,我需要一些解决方案来帮助我了解一些方法:

void myMethod(...)
{
    MyObject obj = new MyObject();
    // do stuff
}

如果此方法已结束或 obj 是否无法访问(这将表明该方法已结束)。

我正在编写一个小型 Java 代理,我希望有一些技术可以让我确定此方法已结束或 obj 无法访问……在我的情况下,“do stuff”部分根本不使用 obj . 它不会将此变量传递到其他地方或将其添加到某个集合中。

我知道通过 Weak/Soft/Phantom-References 我可以部分实现这一点。如果调用 GC,则通过:

void myMethod(...)
{
    MyObject obj = new MyObject();
    WeakReference objReference = new WeakReference(obj);

    // do stuff
}

我总是可以在不同的地方验证:

    if (objReference.get() == null) ...

然而,这只有在 GC 发生时才可能成立。

有没有其他方法可以实现这一目标?例如,一些标记 JVM 可能会放在这个变量上,因为很明显这是一个绝对可以垃圾回收的本地变量......

我不想依赖 ASM - 并为所有这些方法添加一个 try-finally 包装器。希望有一个更微妙的、基于参考的解决方案。

4

1 回答 1

2

做到这一点的唯一可靠方法……我能想到的……是使用回调/侦听器;例如

public MyClass

    void myMethod(Function<MyClass, Void> onCompletion) {
        try {
            // Do stuff
        } finally {
            onCompletion.apply(this);
        }
    }

您还可以使用MethodHandles.tryFinally为您的方法创建方法句柄来实现这一点,该方法句柄通过包装方法来实现回调。

任何基于Reference类型的东西都隐含地依赖于垃圾回收。这将很昂贵,并且您几乎无法控制何时收到通知。


有没有其他方法可以实现这一目标?例如,一些标记 JVM 可能会放在这个变量上,因为很明显这是一个绝对可以垃圾回收的本地变量......

AFAIK,不,没有。并且 JVM / JIT 并没有按照您的假设进行;即,它们不会在正常的 GC 周期之前标记一个“明显的”本地来完成或收集。

他们为什么不呢?因为如果发生这种情况,它会使应用程序变慢。唯一的好处是最终确定/参考处理可能会更快发生,但对于编写良好的应用程序来说没有任何区别。编写良好的程序不应该关心何时发生最终确定/参考处理,因为规范明确不保证时间。

事实证明,逃逸分析也无济于事:

现在我知道 JIT 可能会调整告诉 GC 什么仍在范围内的表(请参阅@Holger 的评论;例如finalize() 在 Java 8 中调用强可达对象)。但这不会改变方法的指令顺序。只有 GC 才会关注这些信息……在 GC 运行时

于 2018-08-26T14:37:27.413 回答