高效Java第六条消除过期的对象引用无意识的对象保持
问题的引出
这段程序有一个“内存泄露”,随着GC活动的添加,或者者因为内存占用的不断添加,程序性能降低会逐步体现出来。在极端的情况下,这种内存泄露会导致磁盘交换,甚至导致程序失败(OutOfMemoryError),但是这种失败情况相比照较少见。
内存泄露的地方:一个栈先是增长,而后再收缩,那么,从栈中弹出来的对象将不会被当做垃圾回收,即便使用栈的程序不再引用这些对象,它们也不会被回收。
栈内部维护着对这些对象的过期引用(永远也不会再被解除的引用)。
elements数组中下标小于size的那些元素都是过期的。
无意识的对象保持导致的问题
在支持垃圾回收的语言中,内存泄露是很隐蔽的,无意识的对象保持。
一个对象引用被无意识地保留起来,那么,GC不仅不会解决这个对象,而且也不会解决这个对象所引用的所有其余对象,因而有可能会对性能造成潜在的重大影响。
无意识的对象保持修复方法
一旦对象引用已经过期,只要清空这些引用就可。
清空过期引用的另一个好处是,假如它们以后又被错误地解除引用,程序会立即抛出NullPointerException异常,而不是悄悄地错误运行下去。
清空对象引用应该是一种例外,而不是一种规范行为
清理过期引用最好的办法是让包含该引用的变量结束其生命周期。
清空引用的时机
Stack类自己管理内存。存储池包含了elements数组的元素。数组活动区域中的元素是已分配的,而数组其他部分的元素则是自由的。但是GC并不知道这一点;对于GC而言,elements数组中的所有对象引用都同等有效。只有程序员知道数组的非活动部分是不重要的。程序员可以把这个情况告知GC:一旦数组元素变成了非活动部分的一部分,程序员就手工清空这些数组元素。
只需类是自己管理内存,程序员就应该警惕内存泄露问题。一旦元素被释放掉,则该元素中包含的任何对象引用都应该被清空。
内存泄露的另一个常见来源是缓存
只需在缓存之外存在对某个项的键的引用,该项就有意义,那么即可以用WeakHashMap代表缓存;当缓存中的项过期之后,它们就会自动被删除。记住只有当所要的缓存项的生命周期是由该键的外部引用而不是由值决定时,才有用处。
”缓存项的生命周期能否有意义”并不是很容易确定,随着时间的推移,其中的项会变得越来越没有价值。在这种情况下,缓存应该时不时地清除掉没用的项。这项清理工作可以由一个后端线程来完成,或者在给缓存增加新条目的时候顺便进行清除。
LinkedHashMap类可以使用removeEldestEntry()实现在给缓存增加新条目的时候进行清除。
对于更复杂的缓存,必需直接使用java.lang.ref。
内存泄露的第三个常见的来源是监听器和其余回调。
用户端在API中注册回调,却没有显示地取消注册。
确保回调立即被当做垃圾回收的最佳方法是只保存它们的弱引用,例如,只将它们保存成中的键。
?为了让学习变得轻松、高效,今天给大家免费分享一套Java教学资源。帮助大家在成为Java架构师的道路上披荆斩棘。需要资料的欢迎加入学习交流群:9285,05736
1. 本站所有资源来源于用户上传和网络,如有侵权请邮件联系站长!
2. 分享目的仅供大家学习和交流,您必须在下载后24小时内删除!
3. 不得使用于非法商业用途,不得违反国家法律。否则后果自负!
4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解!
5. 如有链接无法下载、失效或广告,请联系管理员处理!
6. 本站资源售价只是摆设,本站源码仅提供给会员学习使用!
7. 如遇到加密压缩包,请使用360解压,如遇到无法解压的请联系管理员
开心源码网 » 高效Java第六条消除过期的对象引用无意识的对象保持