如何避免回调中的内存泄漏?

发布于 2024-09-01 20:37:42 字数 273 浏览 2 评论 0原文

有效的Java 说:

内存泄漏的第三个常见来源 是监听器和其他回调。如果 你实现了一个 API,其中客户端 注册回调但不注册 明确取消注册它们,他们会 积累,除非你采取一些 行动。确保的最好方法是 回调被垃圾收集 即刻是只存储弱 对它们的引用,例如 仅将它们作为键存储在 WeakHashMap。

我是 Java 初学者。有人可以教我如何在回调中创建弱引用并告诉我他们如何解决内存泄漏问题吗?谢谢。

Effective Java says:

A third common source of memory leaks
is listeners and other callbacks. If
you implement an API where clients
register callbacks but don’t
deregister them explicitly, they will
accumulate unless you take some
action. The best way to ensure that
callbacks are garbage collected
promptly is to store only weak
references to them, for instance, by
storing them only as keys in a
WeakHashMap.

I am a beginner in Java. Could somebody teach me how to create weak references in callbacks and tell me how they solve the memory leak problems? Thanks.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

最美的太阳 2024-09-08 20:37:42

阅读 这篇文章的

要点是:

您可以将直接引用视为
不需要强引用
额外的编码来创建或访问
目的。其余三种类型
引用是子类
参考类中找到
java.lang.ref 包。软参考
由 SoftReference 提供
类,弱引用
WeakReference 类和幻像
参考文献来自 PhantomReference。

软引用就像数据缓存。
当系统内存不足时,垃圾
收集器可以任意释放
其唯一引用是软对象
参考。换句话说,如果有
没有对对象的强引用,
该对象是
发布。垃圾收集器是
需要释放任何软
抛出之前的参考文献
内存不足异常。

弱引用比软引用更弱
参考。如果仅参考
一个对象是弱引用,
垃圾收集器可以回收
任何时候对象使用的内存。
没有低要求
记忆情况。通常,记忆
对象使用的内容被回收
垃圾收集器的下一次传递。

与清理相关的虚拟引用
任务。他们提供了一个通知
紧邻垃圾之前
收集器执行终结
处理并释放对象。考虑
这是一种在内部执行清理任务的方法
对象。

接下来是 WeakListModel 列表,我不会发布该列表以避免使此响应混乱。

Read this article

The key take aways are :

You can think of direct references as
strong references that require no
extra coding to create or access the
object. The remaining three types of
references are subclasses of the
Reference class found in the
java.lang.ref package. Soft references
are provided by the SoftReference
class, weak references by the
WeakReference class, and phantom
references by PhantomReference.

Soft references act like a data cache.
When system memory is low, the garbage
collector can arbitrarily free an
object whose only reference is a soft
reference. In other words, if there
are no strong references to an object,
that object is a candidate for
release. The garbage collector is
required to release any soft
references before throwing an
OutOfMemoryException.

Weak references are weaker than soft
references. If the only references to
an object are weak references, the
garbage collector can reclaim the
memory used by an object at any time.
There is no requirement for a low
memory situation. Typically, memory
used by the object is reclaimed in the
next pass of the garbage collector.

Phantom references relate to cleanup
tasks. They offer a notification
immediately before the garbage
collector performs the finalization
process and frees an object. Consider
it a way to do cleanup tasks within an
object.

followed by the WeakListModel listing which I won't post to avoid cluttering this response.

饭团 2024-09-08 20:37:42

为了用一个快速(粗略)示例来说明这个概念,请考虑以下情况:

public interface ChangeHandler {
    public void handleChange();
}

public class FileMonitor {

    private File file;
    private Set<ChangeHandler> handlers = new HashSet<ChangeHandler>();

    public FileMonitor(File file) { 
        this.file = file;
    }

    public void registerChangeHandler(ChangeHandler handler) {
        this.handlers.add(handler);
    } 

    public void unregisterChangeHandler(ChangeHandler handler) {
        this.handlers.remove(handler);
    }

    ...
}

如果客户端类随后使用此 FileMonitor API,他们可能会这样做:

public class MyClass {

    File myFile = new File(...);
    FileMonitor monitor = new FileMonitor(myFile);

    public void something() {
        ...
        ChangeHandler myHandler = getChangeHandler();
        monitor.registerChangeHandler(myHandler);
        ...
    }
}

如果 MyClass 的作者> 然后在处理程序完成后忘记调用 unregisterChangeHandler()FileMonitorHashSet 将永远引用已注册的实例,使其保留在内存中,直到 FileMonitor 被销毁或应用程序退出。

为了防止这种情况,Bloch 建议使用弱引用集合而不是 HashSet,这样,如果您的 MyClass 实例被销毁,该引用将从监视器的收藏。

您可以将 FileMonitor 中的 HashSet 替换为 WeakHashMap 并使用处理程序作为键,因为当对该对象的所有其他引用都消失时,后者会自动从集合中删除处理程序。

To illustrate the concept with a quick (crude) example, consider the following:

public interface ChangeHandler {
    public void handleChange();
}

public class FileMonitor {

    private File file;
    private Set<ChangeHandler> handlers = new HashSet<ChangeHandler>();

    public FileMonitor(File file) { 
        this.file = file;
    }

    public void registerChangeHandler(ChangeHandler handler) {
        this.handlers.add(handler);
    } 

    public void unregisterChangeHandler(ChangeHandler handler) {
        this.handlers.remove(handler);
    }

    ...
}

If a client class then uses this FileMonitor API, they might do this:

public class MyClass {

    File myFile = new File(...);
    FileMonitor monitor = new FileMonitor(myFile);

    public void something() {
        ...
        ChangeHandler myHandler = getChangeHandler();
        monitor.registerChangeHandler(myHandler);
        ...
    }
}

If the author of the MyClass then forgets to call unregisterChangeHandler() when it's done with the handler, the FileMonitor's HashSet will forever reference the instance that was registered, causing it to remain in memory until the FileMonitor is destroyed or the application quits.

To prevent this, Bloch is suggesting using a weak-referencing collection instead of the HashSet, so that if your instance of MyClass is destroyed, the reference will be removed from the monitor's collection.

You might replace the HashSet in FileMonitor with a WeakHashMap and use the handlers as the keys, since the latter will automatically remove the handler from the collection when all other references to the object are gone.

可爱暴击 2024-09-08 20:37:42

在这里您还可以找到清晰且实用解释
Android 中的内存泄漏 — 识别、治疗和避免

Here you may find a clear and practical explanation as well:
Memory leaks in Android — identify, treat and avoid

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文