我需要一些解决方案来帮助我说出一些方法,例如:
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
类型的东西都隐含地依赖于垃圾收集。这将是昂贵的,你几乎无法控制何时收到通知。
有没有其他方法来实现这一目标?例如,标记JVM的一些标记可能会放在这个变量上,因为很明显这是一个肯定是垃圾收集的本地...
AFAIK,没有。并且JVM / JIT没有做你所假设的事情;即,在正常的GC循环之前,它们没有标记“明显的”局部用于最终确定或收集。
他们为什么不呢?因为如果发生这种情况会使应用程序变慢。唯一的好处是最终化/参考处理可能会更快地发生,但是对于编写良好的应用程序来说,没有任何区别。一个编写良好的程序不应该关注何时进行最终化/参考处理,因为规范明确地不保证时间。
事实证明逃逸分析也无济于事:
现在我知道JIT可能会调整告诉GC仍在范围内的表格(参见@ Holger的评论;例如finalize() called on strongly reachable object in Java 8)。但这并没有改变方法的指令序列。 GC正在运行时,只有GC关注这些信息......