美文网首页Java 杂谈Android知识
高效Java第六条消除过期的对象引用

高效Java第六条消除过期的对象引用

作者: 每天学点编程 | 来源:发表于2017-07-19 21:25 被阅读0次

问题的引出

这段程序有一个“内存泄露”,随着GC活动的增加,或者由于内存占用的不断增加,程序性能降低会逐渐表现出来。在极端的情况下,这种内存泄露会导致磁盘交换,甚至导致程序失败(OutOfMemoryError),但是这种失败情况相对比较少见。

内存泄露的地方:一个栈先是增长,然后再收缩,那么,从栈中弹出来的对象将不会被当做垃圾回收,即使使用栈的程序不再引用这些对象,它们也不会被回收。

栈内部维护着对这些对象的过期引用(永远也不会再被解除的引用)。

elements数组中下标小于size的那些元素都是过期的。

无意识的对象保持导致的问题

在支持垃圾回收的语言中,内存泄露是很隐蔽的,无意识的对象保持。
一个对象引用被无意识地保留起来,那么,GC不仅不会处理这个对象,而且也不会处理这个对象所引用的所有其他对象,因此有可能会对性能造成潜在的重大影响。

无意识的对象保持修复方法

一旦对象引用已经过期,只需清空这些引用即可。


清空过期引用的另一个好处是,如果它们以后又被错误地解除引用,程序会立即抛出NullPointerException异常,而不是悄悄地错误运行下去。

清空对象引用应该是一种例外,而不是一种规范行为

清除过期引用最好的办法是让包含该引用的变量结束其生命周期。

清空引用的时机

Stack类自己管理内存。存储池包含了elements数组的元素。数组活动区域中的元素是已分配的,而数组其余部分的元素则是自由的。但是GC并不知道这一点;对于GC而言,elements数组中的所有对象引用都同等有效。只有程序员知道数组的非活动部分是不重要的。程序员可以把这个情况告知GC:一旦数组元素变成了非活动部分的一部分,程序员就手工清空这些数组元素。

只要类是自己管理内存,程序员就应该警惕内存泄露问题。一旦元素被释放掉,则该元素中包含的任何对象引用都应该被清空。

内存泄露的另一个常见来源是缓存

只要在缓存之外存在对某个项的键的引用,该项就有意义,那么就可以用WeakHashMap代表缓存;当缓存中的项过期之后,它们就会自动被删除。记住只有当所要的缓存项的生命周期是由该键的外部引用而不是由值决定时,WeakHashMap才有用处。

"缓存项的生命周期是否有意义"并不是很容易确定,随着时间的推移,其中的项会变得越来越没有价值。在这种情况下,缓存应该时不时地清理掉没用的项。这项清除工作可以由一个后台线程来完成,或在给缓存添加新条目的时候顺便进行清理。

LinkedHashMap类可以使用removeEldestEntry()实现在给缓存添加新条目的时候进行清理。

对于更复杂的缓存,必须直接使用java.lang.ref

内存泄露的第三个常见的来源是监听器和其他回调。

客户端在API中注册回调,却没有显示地取消注册。
确保回调立即被当做垃圾回收的最佳方法是只保存它们的弱引用,例如,只将它们保存成WeakHashMap中的键。

总结

由于内存泄露通常不会表现成明显的失败,所以它们可以在一个系统中存在很多年。
只有通过仔细检查代码,或借助于Heap剖析工具才能发现内存泄露问题。

相关文章

  • 高效Java第六条消除过期的对象引用

    问题的引出 这段程序有一个“内存泄露”,随着GC活动的增加,或者由于内存占用的不断增加,程序性能降低会逐渐表现出来...

  • 消除过期的对象引用

    第6条:消除过期的对象引用 1. 为什么要消除过期的对象引用 java虽然有自己的垃圾回收机制,但是并没有那么的智...

  • 第六条消除过期的对象引用

    考虑下面的例子(栈的实现) 这段程序中没有明显的错误,但是隐藏着一个问题 ,即 “内存泄漏” 当一个元素被出...

  • 高效Java第六条消除过期的对象引用无意识的对象保持

    问题的引出 这段程序有一个“内存泄露”,随着GC活动的增加,或者由于内存占用的不断增加,程序性能降低会逐渐表现出来...

  • 消除过期的对象引用

    你能看出以下代码哪里内存泄漏吗? 答案是: pop()方法存在内存泄漏。 内存泄漏可以称为“ 无意识的对象保持(u...

  • 消除过期的对象引用

    什么是过期的对象引用? 我们通过简单的栈实现来引入过期的对象引用。 实际上,这段程序中并没有很明显的错误。无论如何...

  • 消除过期的对象引用

    某些类内部维护着对象的过期引用(指永远也不会再被解除的引用),这些对象不会被当作垃圾回收,产生了内存泄露(这类内存...

  • 消除过期的引用对象

    C或者C++是手工管理内存语言,java语言是自带垃圾回收,程序员的工作就很容易,因为当你用完了对象之后,他会被自...

  • [Effective Java] (06)消除过期的对象引用

    虽然在Java语言中拥有垃圾收集(GC)回收程序,在创建对象后,不用程序员手动回收对象,但在某些情况下依然会造成内...

  • java代码优化——消除过期的对象引用

    很多人可能在想这么一个问题:Java有垃圾回收机制,那么还存在内存泄露吗?答案是肯定的,所谓的垃圾回收GC会自动管...

网友评论

    本文标题:高效Java第六条消除过期的对象引用

    本文链接:https://www.haomeiwen.com/subject/xpjkkxtx.html