内容简介:Java语言的一大特点就是可以自动进行垃圾回收处理,无需开发人员过于关注系统资源的释放情况。自动垃圾收集虽然大大减轻了开发人员的工作量,但是也增加了软件系统的负担。一个不合适的垃圾回收方法和策略将会对系统性能造成不良影响。引用计数法是最经典古老的一种垃圾收集方法,它的实现也很简单:对于一个对象A,只要有任何一个对象引用了A,则A的计数器就加1,当引用失效时,引用计数器就减1.只要对象A的引用计数器的值为0,则对象A就不可能再被使用。引用计数法实现简单,只需要为每一个对象配备一个整型计数器即可。但是,它存在一
Java语言的一大特点就是可以自动进行垃圾回收处理,无需开发人员过于关注系统资源的释放情况。自动垃圾收集虽然大大减轻了开发人员的工作量,但是也增加了软件系统的负担。一个不合适的垃圾回收方法和策略将会对系统性能造成不良影响。
1. 引用计数法
引用计数法是最经典古老的一种垃圾收集方法,它的实现也很简单:对于一个对象A,只要有任何一个对象引用了A,则A的计数器就加1,当引用失效时,引用计数器就减1.只要对象A的引用计数器的值为0,则对象A就不可能再被使用。
引用计数法实现简单,只需要为每一个对象配备一个整型计数器即可。但是,它存在一个很严重的问题,即无法处理循环引用的情况,因此在 Java 的垃圾回收器中没有使用这种算法。
一个简单的循环引用示例如下:
对象A和对象B循环引用,此时他们的引用计数器都不为0,但是在系统中已经找不到第三个对象引用了A或者B,也就是说,A和B应该是被回收的垃圾。但是因为循环引用而无法被识别,最终可能会导致内存泄漏。
2. 标记-清除法
标记-清除法是现代垃圾回收算法的基础。
它将垃圾回收分为两个阶段:标记阶段和清除阶段。一种可行的实现是:
- 在标记阶段,标记所有从根节点出发的可达对象。因此,所有未被标记的对象就是未被引用的垃圾对象。
- 在清除阶段,清除所有未被标记的对象。
而标记-清除法可能产生的最大问题就是空间碎片。回收之后的空间不是连续的,不连续的内存空间的工作效率要低于连续的空间,这是标记-清除法最大的缺点。
3.复制算法
与标记-清除法相比,复制算法是一种相对高效的回收算法。
它的核心思想是:将内存分为两部分,每次只使用其中一部分。在垃圾回收时,将正在使用的内存中的存货对象复制到未使用的内存块中,之后清除正在使用的内存块中的所有对象,交换两个内存的角色,完成垃圾回收。
如果系统中的垃圾对象很多,那么复制算法需要复制的存活对象的数量也不会很多,因此当需要使用复制算法时还是比较高效的。又因为所有对象都会被统一复制到新的内存空间中,所以可以保证回收后的内存空间是没有碎片的。
虽然有以上两大有点,但是复制算法的代价缺点是将系统内存折半。因此单纯的复制算法会让人无法接受。
在Java的新生代串行垃圾回收器中,使用了复制算法。新生代分为eden空间、from空间和to空间三个部分。其中from和to空间可以视为用于复制的两块大小相同、地位相等,且角色可以互换的空间块,它们也被称为survivor空间,即幸存者空间,用于存放未被回收的对象。
在垃圾回收时,eden空间中的存活对象会被复制到未使用的survivor空间中(假设为to),正在使用的survivor空间(假设为from)中的年轻对象也会被复制到to空间中(大对象或者老年对象会直接进入老年代,如果to空间已经满了,则对象也会直接进入老年代)。此时eden和from空间中的剩余对象将都是垃圾对象,可以直接清空,to空间则存放此次回收后存活的对象。
这样改进后的复制算法既保证了空间的连续性,又避免大量内存空间被浪费。
4. 标记-压缩算法
复制算法的高效性是建立在存活对象少,垃圾对象多的前提下。这种情况普遍存在于年轻代,但是在老年代,更常见的情况是大部分对象都是存活对象,如果使用复制算法,由于存活对象多,复制的成本也会很高。
基于老年代垃圾回收的特性,需要使用新的算法,而标记-压缩算法是老年代的一种回收算法,它在标记-清除算法之上做了一些优化。
它和标记-清除算法不同之处在于:在清除阶段,它会将所有的存活对象压缩到内存的另一端。之后清理边界之外的所有空间。这种算法既避免了碎片的产生,又不需要两块相同的内存空间,因此性价比较高。
5. 增量算法
对大部分的垃圾回收算法而言,在垃圾回收的过程中,应用软件的所有线程都会挂起,暂停一切正常工作,等待来回收的完成。如果垃圾回收时间很长,则应用程序会被挂起很久,这会严重影响用户体验和系统稳定性。
增量算法的基本思想就是,让垃圾回收线程和应用线程交替执行,每次只收集一小片区域的内存空间,接着切换应用程序线程。如此往复知道垃圾回收完成。
使用这种方式进行垃圾回收可以减少系统的停顿时间,但是因为线程切换和上下文转换的消耗,会使得垃圾回收的总体成本上升,造成系统吞吐量的下降。
6.分代
前面介绍的几种垃圾回收算法没有哪一种可以完全替代其他算法,它们有各自的优点和缺点。因此,根据垃圾回收对象的特性,使用合适的算法回收,才是明智的选择。
分代就是基于这种思想,它将内存区域根据对象特点分为几块,根据每块内存区间的特点,使用不同的回收算法,提高垃圾回收的效率。
Linux公社的RSS地址 : https://www.linuxidc.com/rssFeed.aspx
本文永久更新链接地址: https://www.linuxidc.com/Linux/2019-01/156333.htm
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- 垃圾回收算法(7)-分代回收算法
- 必知必会JVM垃圾回收——对象搜索算法与回收算法
- 垃圾回收算法(6)-增量算法
- 对象回收判定与垃圾回收算法-JVM学习笔记(1)
- jvm垃圾回收算法
- 浅谈垃圾回收算法
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
深入浅出Struts 2
Budi Kuniawan / 杨涛、王建桥、杨晓云 / 人民邮电出版社 / 2009-04 / 59.00元
本书是广受赞誉的Struts 2优秀教程,它全面而深入地阐述了Struts 2的各个特性,并指导开发人员如何根据遇到的问题对症下药,选择使用最合适的特性。作者处处从实战出发,在丰富的示例中直观地探讨了许多实用的技术,如数据类型转换、文件上传和下载、提高Struts 2应用的安全性、调试与性能分析、FreeMarker、Velocity、Ajax,等等。跟随作者一道深入Struts 2,聆听大量来之......一起来看看 《深入浅出Struts 2》 这本书的介绍吧!