2013-08-06 06:30:01

阅读( 244 )

在本文中,他将解释 Reference 对象的另外一种形式,即软引用(soft references),用于帮助垃圾收集器管理内存使用和消除潜在的内存泄漏。

垃圾收集可以使 Java 程序不会出现内存泄漏,至少对于比较狭窄的 “内存泄漏” 定义来说如此,但是这并不意味着我们可以完全忽略 Java 程序中的对象生存期(lifetime)问题。当我们没有对对象生命周期(lifecycle)引起足够的重视或者破坏了管理对象生命周期的标准机制时,Java 程序中通常就会出现内存泄漏。例如,上一次 我们看到了,不能划分对象的生命周期会导致,在试图将元数据关联到瞬时对象时出现意外的对象保持。还有一些其他的情况可以类似地忽略或破坏对象生命周期管理,并导致内存泄漏。

对象游离

一种形式的内存泄漏有时候叫做对象游离(object loitering),是通过清单 1 中的 LeakyChecksum 类来说明的,清单 1 中有一个 getFileChecksum() 方法用于计算文件内容的校验和。getFileChecksum() 方法将文件内容读取到缓冲区中以计算校验和。一种更加直观的实现简单地将缓冲区作为 getFileChecksum() 中的本地变量分配,但是该版本比那样的版本更加 “聪明”,不是将缓冲区缓存在实例字段中以减少内存 churn。该 “优化”通常不带来预期的好处;对象分配比很多人期望的更便宜。(还要注意,将缓冲区从本地变量提升到实例变量,使得类若不带有附加的同步,就不再是线程安全的了。直观的实现不需要将 getFileChecksum() 声明为 synchronized,并且会在同时调用时提供更好的可伸缩性。)

清单 1. 展示 “对象游离” 的类

// BAD CODE – DO NOT EMULATE

public class LeakyChecksum {

private byte[] byteArray;

public synchronized int getFileChecksum(String fileName) {

int len = getFileSize(fileName);

if (byteArray == null || byteArray.length < len)

byteArray = new byte[len];

readFileContents(fileName, byteArray);

// calculate checksum and return it

}

}

这个类存在很多的问题,但是我们着重来看内存泄漏。缓存缓冲区的决定很可能是根据这样的假设得出的,即该类将在一个程序中被调用许多次,因此它应该更加有效,以重用缓冲区而不是重新分配它。但是结果是,缓冲区永远不会被释放,因为它对程序来说总是可及的(除非 LeakyChecksum 对象被垃圾收集了)。更坏的是,它可以增长,却不可以缩小,所以 LeakyChecksum 将永久保持一个与所处理的最大文件一样大小的缓冲区。退一万步说,这也会给垃圾收集器带来压力,并且要求更频繁的收集;为计算未来的校验和而保持一个大型缓冲区并不是可用内存的最有效利用。

LeakyChecksum 中问题的原因是,缓冲区对于 getFileChecksum() 操作来说逻辑上是本地的,但是它的生命周期已经被人为延长了,因为将它提升到了实例字段。因此,该类必须自己管理缓冲区的生命周期,而不是让 JVM 来管理。

软引用

弱引用如何可以给应用程序提供当对象被程序使用时另一种到达该对象的方法,但是不会延长对象的生命周期。Reference 的另一个子类 —— 软引用 —— 可满足一个不同却相关的目的。其中弱引用允许应用程序创建不妨碍垃圾收集的引用,软引用允许应用程序通过将一些对象指定为 “expendable” 而利用垃圾收集器的帮助。尽管垃圾收集器在找出哪些内存在由应用程序使用哪些没在使用方面做得很好,但是确定可用内存的最适当使用还是取决于应用程序。如果应用程序做出了不好的决定,使得对象被保持,那么性能会受到影响,因为垃圾收集器必须更加辛勤地工作,以防止应用程序消耗掉所有内存。

高速缓存是一种常见的性能优化,允许应用程序重用以前的计算结果,而不是重新进行计算。高速缓存是 CPU 利用和内存使用之间的一种折衷,这种折衷理想的平衡状态取决于有多少内存可用。若高速缓存太少,则所要求的性能优势无法达到;若太多,则性能会受到影响,因为太多的内存被用于高速缓存上,导致其他用途没有足够的可用内存。因为垃圾收集器比应用程序更适合决定内存需求,所以应该利用垃圾收集器在做这些决定方面的帮助,这就是件引用所要做的。

如果一个对象惟一剩下的引用是弱引用或软引用,那么该对象是软可及的(softly reachable)。垃圾收集器并不像其收集弱可及的对象一样尽量地收集软可及的对象,相反,它只在真正 “需要” 内存时才收集软可及的对象。软引用对于垃圾收集器来说是这样一种方式,即 “只要内存不太紧张,我就会保留该对象。但是如果内存变得真正紧张了,我就会去收集并处理这个对象。” 垃圾收集器在可以抛出 OutOfMemoryError 之前需要清除所有的软引用。

通过使用一个软引用来管理高速缓存的缓冲区,可以解决 LeakyChecksum 中的问题,如清单 2 所示。现在,只要不是特别需要内存,缓冲区就会被保留,但是在需要时,也可被垃圾收集器回收:

清单 2. 用软引用修复 LeakyChecksum

public class CachingChecksum {

private SoftReferencebufferRef;

public synchronized int getFileChecksum(String fileName) {

int len = getFileSize(fileName);

byte[] byteArray = bufferRef.get();

if (byteArray == null || byteArray.length < len) {

byteArray = new byte[len];

bufferRef.set(byteArray);

}

readFileContents(fileName, byteArray);

// calculate checksum and return it

}

}

分享给朋友:

亲~ 如果您有更好的答案 可在评论区发表您独到的见解。

您想查看更多的信息:

面试题

java软引用_什么是软引用? 有什么作用相关推荐

  1. 方法引用_通过对象名引用成员方法

    方法引用符 双冒号:: 为引用运算符,而它所在的表达式被称为方法引用.如果Lambda要表达的函数方案已经存在于某个方 法的实现中,那么则可以通过双冒号来引用该方法作为Lambda的替代者. 语义分析 ...

  2. java 正则 反向引用_正则之反向引用

    前言 某日在逛stackoverflow时,发现侧边栏的Hot Network Questions里有一例codegolf的问题Does it repeat?. 挑战 好奇之下点入观看,该题主的挑战如 ...

  3. java怎么编写软键盘_安卓手机软键盘操作

    inputMethodManager = (InputMethodManager) getActivity().getSystemService(Context.INPUT_METHOD_SERVIC ...

  4. java面试分为_【中软国际Java面试】面试分为两轮。-看准网

    面试分为两轮. 面试分为两轮.一面技术面,看了往年的面经,感觉真的好水,不过我面试的时候感觉还是有点难度的,范围很广.数据结构和算法问了8大排序,问了有哪些数据结构,快排的思想,基准怎么找,二分法查找 ...

  5. perl数组硬引用_带有哈希引用的Perl数组引用(Perl Array Reference with hash reference)

    带有哈希引用的Perl数组引用(Perl Array Reference with hash reference) my $var1=[{'a'=>'1','b'=>'2'},1]; pr ...

  6. nstimer循环引用_解决NSTimer循环引用导致内存泄漏的六种方法

    demo放在了GitHub 内存泄漏的原因: self强引用timer.timer添加在runloop上,只要timer不销毁self就销毁不了.当然了你可以选择在viewWillDisappear中 ...

  7. vue 公用页面引用_关于vue全局引用公共的js和公共的组件的折腾

    前沿 最近在项目开发中遇到一些需要全局引用的公共js,或者公共组件,早就烦死了那种每个页面都写一遍,都引用一个js的写法,正好vue解决了这个额问题,于是乎就开始折腾,折腾的过程中也发现了一些自己之前 ...

  8. python字典弱引用_如何使用弱引用优化 Python 程序的内存占用?

    Python 的垃圾回收机制通过引用计数来决定一个对象要不要被回收.当一个对象被引用次数为0时,它就会被作为垃圾回收从而释放 Python 内存.但有些情况下,我们的代码可能在不经意间导致某些实际上我 ...

  9. win10 软路由_超小软路由Nanopi R2S折腾记

    全世界只有不到0.00~1 % 的人关注了我们 得到你的关注是小帮的幸运 垂涎软路由已久,这次终于对它下手 因为是初次体验软路由,为了控制成本,本次选择了Nanopi r2s作为折腾对象,小巧精致的外 ...

  10. vant 软键盘_移动端软键盘监听(弹出,收起),及影响定位布局的问题

    移动端软键盘监听(弹出,收起),及影响定位布局的问题 一:移动端软键盘监听(弹出,收起) 1.监听resize ( Android) var winHeight = $(window).height( ...

最新文章

  1. 访问SAP时提示报错SAP GUI for Windows 720窗口
  2. transient-java 关键字
  3. 大数据平台蓝图_数据科学面试蓝图
  4. 又做了3个极品菜[图]
  5. python基础知识资料包-Python基础知识总结——史上最全系列
  6. python可视化分析网易云音乐评论_网易云音乐热门评论api分析
  7. 开源 java CMS - FreeCMS2.5 标签 infoPage
  8. OpenLDAP(2.4.3x)服务器搭建及配置说明
  9. Trick(二)——获取一个网页的 title 信息
  10. 解决 min-width 在 IE6 中无效的方法
  11. 科技四巨头展望:战线***升级 软硬界限模糊
  12. CentOs 开启ssh服务
  13. The proxy server is refusing connections 怎么解决呢?
  14. 基站定位(Google API)
  15. 史上最全Android版本号信息:)_我是亲民_新浪博客
  16. Python列表解析式-生成器
  17. 2380318-57-8,Thalidomide-O-PEG4-Azide通过点击化学与炔烃或DBCO、BCN连接的分子反应的PROTAC连接物
  18. C#丨DataGridView控件获取选中行的某一列的值
  19. 强大的代码编档工具—Doxygen
  20. Node.js | 从前端到全栈的必经之路

热门文章

  1. 【教程】win10 固态硬盘卡机卡死卡顿的真正原因!
  2. python数据建模工具_Python数据分析、挖掘常用工具
  3. JVM性能调优1:JVM性能调优理论及实践(收集整理)
  4. 阿里云服务器密码重置
  5. mix3android auto,小米MIX3滑盖全面屏值不值得买?三天真实体验说说优缺点
  6. 【HDU5442】 Favorite Donut(后缀数组)
  7. Euclid算法和拓展欧几里得算法
  8. Ajax关于readyState和status
  9. 21个数据科学家面试必须知道的问题和答案
  10. java.lang.Byte cannot be cast to java.lang.Integer,sql 到 java 类型转换遇到的问题