关于java内存泄露

来源:互联网 发布:mac git客户端使用 编辑:程序博客网 时间:2024/04/29 19:19
 
1)实际上无用,而还被引用的对象,GC就无能为力了(事实上GC认为它还有用),这一点是导致内存泄漏最重要的原因。
 
例1
Java是通过垃圾收集器(Garbage Collection,GC)自动管理内存的回收,程序员不需要通过调用函数来释放内存,但它只能回收无用
并且不再被其它对象引用的那些对象所占用的空间。在下面的代码中,循环申请Object对象,并将所申请的对象放入一个Vector中,
如果仅仅释放对象本身,但是因为Vector仍然引用该对象,所以这个对象对GC来说是不可回收的。因此,如果对象加入到Vector后,
还必须从Vector中删除,最简单的方法就是将Vector对象设置为null。
 
Vector v = new Vector(10);
for (int i = 1; i < 100; i++)
{Object o = new Object();
v.add(o);
o = null;}//此时,所有的Object对象都没有被释放,因为变量v引用这些对象
 
例2 失效监听器
这类内存漏洞是一种常见的错误模式 — 称为“失效的监听器”错误 — 通常源于监听器模式的错误应用。监听器模式允许类将事件相互通知给对方;它是 Observer/Observable 模式的一个特别的类,包括一个主题和一个观察器。监听器通常用于为发生在对象上的事件指定事件处理器。一些常用的事件类型是:
 
GUI 事件通常由专用监听器类来处理,这些类为 AWT、Swing 和其他 GUI 库中的 GUI 事件实现 java.util.EventListener 接口。
数据库连接事件通常由实现 javax.sql.ConnectionEventListener 接口的监听器来处理。
 
虽然监听器模式被广泛地采用,但如果使用不当很容易出错并可能导致内存漏洞。我们将通过演示监听器在内部实现的方式说明可能出现的漏洞。
 
考虑这样一种情况:我们注册了一个监听器,等待在一个窗口小部件 (widget) 中可能发生的事件(见下图)。从根集合(根是对活动对象的引用;而根集合是具有引用的所有可访问对象的集合)可访问的监听器表包含了所有可能的监听器的链接列表;全局事件表指向该监听器表。当事件在窗口小部件中发生时,事件分配器遍历监听器表并调用适当监听器上的事件处理器。监听器表包含对监听器的引用,以便它能够在事件来临时传递该事件。 
但是,如果该引用被保留,则由于可以从根集合中访问而不会回收该对象。在很多情况下,该对象可能会耗费大量系统资源。它可能是一个利用本地系统资源或利用有限资源的大型 GUI 对象,如数据库连接。虽然监听器通常是小对象,并且因此可能不会立刻产生问题,但是保持可访问状态(并且因此而未被回收)的较大对象可能会影响性能,并且可能由于它们对内存的影响而导致系统崩溃。
所以当使用监听器模式时,确保注册与取消注册监听器的调用与所有执行路径相匹配。
 
原创粉丝点击