gpt4 book ai didi

java - 使用 java.lang.ref.Cleaner 替代 Object.finalize

转载 作者:行者123 更新时间:2023-12-04 01:12:19 24 4
gpt4 key购买 nike

我需要清理 JNI 调用分配的资源。通过覆盖 Object.finalize() 方法很容易做到这一点。由于从 Java 9 开始不推荐使用此方法,因此我尝试使用新的 java.lang.ref.Cleaner 类实现相同的目的。

下面是在实例被垃圾回收之前调用ToBeCleaned.cleanUp方法的代码:

import java.lang.ref.Cleaner;
import java.lang.ref.WeakReference;

public class ToBeCleaned {

private static Cleaner cleaner = Cleaner.create();

public ToBeCleaned() {
cleaner.register(this, new CleanRunnable(this));
}

void cleanUp () {
// do cleanup
}


static class CleanRunnable implements Runnable {
// It has to be weak reference, otherwise ToBeCleaned instance
// would never be eligible for GC
private WeakReference<ToBeCleaned> toBeCleanedWeakReference;

CleanRunnable(ToBeCleaned toBeCleaned) {
this.toBeCleanedWeakReference = new WeakReference<>(toBeCleaned);
}

@Override
public void run() {
toBeCleanedWeakReference.get().cleanUp();
}
}
}

我的问题:这是正确的方法吗?

最佳答案

您的方法有缺陷。 “清理操作”不得依赖于对使用 Cleaner 注册的实例的访问权限。

简而言之,在您的代码中调用 toBeCleanedWeakReference.get() 将返回 null,因为 ToBeCleaned 实例将在至少从我们的角度来看,那一点收集的垃圾。

正确的方法是以某种方式引用需要清理的资源,而无需“通过”ToBeCleaned 实例。通常这意味着:

  1. 使清洁操作和资源成为同一个对象(不同于使用 Cleaner 注册的对象)。 documentation Cleaner 的示例展示了这种方法。

  2. 在实例化清理操作时,将对资源的引用传递给清理操作,而不是向 Cleaner 注册的对象。这是一个例子:

    public class ToBeCleaned implements AutoCloseable {

    // documentation suggests you should preferably have one
    // Cleaner instance per library
    private static final Cleaner CLEANER = ...;

    private final Cleaner.Cleanable cleanable;
    private final SomeResource resource;

    public ToBeCleaned() {
    resource = ...;
    cleanable = CLEANER.register(this, new CleaningAction(resource));
    }

    @Override
    public void close() {
    cleanable.clean();
    }

    private static class CleaningAction implements Runnable {

    private final SomeResource resource;

    CleaningAction(SomeResource resource) {
    this.resource = resource;
    }

    @Override
    public void run() {
    // clean up 'resource'
    }
    }
    }

两个示例都实现了 AutoCloseable。这让您的 API 用户能够按需释放资源,而不是等待垃圾收集器启动(这使得 Cleaner 更像是一个“备份”)。

关于java - 使用 java.lang.ref.Cleaner 替代 Object.finalize,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64459003/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com