问候,
介绍Java因其垃圾回收机制而受到赞扬(并鄙视)。 在
年和几种Java版本GC机制已经从简单的标记变为
和清除收集器导致早期的Java程序暂时冻结
有时它不应该冻结为高度复杂的多线程,
复杂的“世代清除”收集机制,难以完成工作
其余的应用程序或用户可以注意到。
与许多其他编程相比,Java的内存管理轻而易举
语言。 事情仍然可能出错或失控:内存泄漏。 确切地说,
这实际上不是C语言程序中的“泄漏”:
int main() {
char* p= malloc(42);
p= malloc(54);
}
后代丢失了前42个字节,因为程序中没有任何内容
“指向”或“引用”了。 在Java中不是这样:Java中的内存泄漏
意味着某些东西仍然指向持有的特定内存
一个对象值,但我们不知道还有其他东西指向它。 但是我们
确保某些东西指向它,否则垃圾收集器将具有
找到了。
Java内存泄漏更像是“粘性内存”,例如在下面的某处嚼口香糖
您的鞋子:您不知道它在那儿,但它仍然在那儿。
如果您不小心在某种循环中实施了此类不良行为
您可以指望它会在不久的将来出现OutOfMemory异常
Java虚拟机抛出的垃圾邮件将使您的应用程序丧命。
一些核心课程提供了一些基础知识,可以对
上述情况。 接下来的段落描述了这些构建块。
参考文献薄弱从功能上讲,WeakReference类仅此而已:
public class WeakReference<T> {
private T referent;
public WeakReference(T referent) { this.referent= referent; }
public T get() { return referent; }
}
请注意,这不是WeakReference类的真正源代码,它只是
展示了此类对象在功能上的行为。
真正的功能并不多:您可以将WeakReference传递给任何对象
在构造时类型为T的对象,以后可以将对象T取回
你再次想要它; 没关系
幕后还有很多事情发生:实例化WeakReference时
对象,将其自身注册到垃圾收集器,即与之通信
我们背后的敌人。
激活垃圾收集器后,它会跟踪引用的对象
所有的WeakReferences。 如果这些对象除以外没有其他引用
由WeakReferences持有的参考文献,它们是在
垃圾收集器,即WeakReference对象中的引用T设置为
null,该对象因后代而丢失。
如果T对象被不符合垃圾回收条件的另一个对象引用
T对象本身将是安全的。
总结:如果对对象的唯一引用是通过WeakReference对象,
该对象仍然有资格进行垃圾收集。
如果没有其他内容引用WeakReference对象,则引用对象将仅
如果其他事物直接引用该引用对象,则该方法是安全的。 弱参考
但是该对象有资格进行垃圾收集。 用外行的话来说:弱引用
是派对装腔作势者:当他们最后引用物体时,他们怯ly
将该对象移交给垃圾收集器收割机。
粘性物体粘滞对象失败的常见情况是发生Swing对象时
注册为其他对象的侦听器。 没有注册对象时
不再需要它们,其他对象仍将它们称为侦听器,以
他们已注册。
令人讨厌的是那些注册的侦听器不知道什么时候不知道
该应用程序不再需要。 应用到
“手动”在不再需要侦听器时将其删除,并且,
这样做容易出错(程序员是人类,人类很愚蠢)
因为他们经常犯错误)。
在这里,WeakReferences可能会有所帮助:想象我们这样做:而不是注册
一个对象的侦听器,我们注册一个WeakReference并制作原始对象
监听器,WeakReference对象本身的引用对象。 诀窍的核心
是当WeakReference对象的'get()'方法返回null时,
引用对象已被垃圾回收。
为了示例,让我们处理需要注册的ActionListener
到AbstractButtons。
AbstractButton包含以下方法的实现:
public void addActionListener(ActionListener listener);
public void removeActionListener(ActionListener listener);
仅仅因为AbstractButton恰好是其中所有内容的基类
使用ActionListeners的Swing仅需要为
AbstractButton类(为Swing的设计加油!)。
如果我们想将WeakReference注册为ActionListener,则*
一个ActionListener本身。 没问题,这里是:
public class ActionReference extends WeakReference<ActionListener>
implements ActionListener {
private AbstractButton button;
ActionReference(ActionListener listener, AbstractButton button) {
super(listener);
this.button= button;
button.addActionListener(this);
}
public void actionPerformed(ActionEvent event) {
ActionListener listener= get();
if (listener == null)
button.removeActionListener(this);
else
listener.actionPerformed(event);
}
}
构造函数将AbstractButton和ActionListener作为其参数。
它跟踪按钮并将其自身注册为ActionListener。
当按钮触发事件时,ActionReference的actionPerformed方法为
调用。 它检查实际的ActionListener是否已被垃圾回收
集。 如果是这样,它将从按钮中注销自己。 如果真正的侦听器仍然存在,
将该事件委托给真实的侦听器,就像将其注册到
直接点击。
对于任何“按钮”和任何“侦听器”,侦听器的注册方式如下:
new ActionReference(listener, button);
这就是您要做的一切:当不再需要侦听器时,我们的ActionReference
通过从事件源中删除自身来解决此问题。 请注意,我没有使用
事件对象本身的“ getSource()”方法。 这样可以防止移除
来自错误对象的ActionListener,如果事件的触发是综合的
由应用程序本身。
这个单一的小类可以防止内存泄漏或应用程序中的“粘性对象”。
我相信您现在可以弄清楚如何安全处理其他类型的事件。
希望直到下周
亲切的问候,
乔斯
From: https://bytes.com/topic/java/insights/705335-weakreferences