有什么方法可以判断方法是否结束或本地方法不再使用?

any way to tell if a method ended or local in method in no longer in use?

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

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 包装器。希望有一个更微妙的、基于参考的解决方案。

我能想到的唯一可靠方法...就是使用回调/侦听器;例如

public MyClass

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

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

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


Is there any alternative way to achieve this? For example, some marking the JVM may put on this variable since it is obvious this is a local that is definitely garbage-collectible...

据我所知,不,没有。而 JVM / JIT 并没有按照您的假设进行操作;也就是说,它们不会在正常的 GC 周期之前将 "obvious" 本地标记为完成或收集。

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

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

现在我知道 JIT 可能会调整表,告诉 GC 什么仍在范围内(请参阅@Holger 的评论;例如 finalize() called on strongly reachable object in Java 8)。但这不会改变方法的指令顺序。只有 GC 会关注那个信息... 而 GC 是 运行.