Java垃圾回收机制

堆空间的基本结构

eden区、s0区、s1区都属于新生代,tentired 区属于老年代。⼤部分情况,对象都会⾸先在 Eden 区域分配,在⼀次新⽣代垃圾回收后,如果对象还存活,则会进⼊ s0 或者 s1,并且对象的年龄还会加 1(Eden区->Survivor 区后对象的初始年龄变为1),当它的年龄增加到⼀定程度(默认为15岁),就会被晋升到⽼年代中。对象晋升到⽼年代的年龄阈值,可以通过参数 -XX:MaxTenuringThreshold 来设置。另外,⼤对象和⻓期存活的对象会直接进⼊⽼年代。

Minor GC和Full GC的区别

⼤多数情况下,对象在新⽣代中 eden 区分配。当 eden 区没有⾜够空间进⾏分配时,虚拟机将发起⼀次Minor GC。
新生代GC(Minor GC):指发⽣新⽣代的的垃圾收集动作,Minor GC⾮常频繁,回收速度⼀般也比较快。
老年代GC(Major GC/Full GC):指发⽣在⽼年代的GC,出现了Major GC经常会伴随⾄少⼀次的Minor GC(并⾮绝对),Major GC的速度⼀般会⽐Minor GC的慢10倍以上。

判断对象是否死亡的两种方式

引用计数法:给对象中添加⼀个引⽤计数器,每当有⼀个地⽅引⽤它,计数器就加1;当引⽤失效,计数器就减1;任何时候计数器为0的对象就是不可能再被使⽤的;
可达性分析算法:这个算法的基本思想就是通过⼀系列的称为 “GC Roots” 的对象作为起点,从这些节点开始向下搜索,节点所⾛过的路径称为引⽤链,当⼀个对象到 GC Roots 没有任何引⽤链相连的话,则证明此对象是不可⽤的。

强引用,软引用,弱引用,虚引用

强引用:以前我们使⽤的⼤部分引⽤实际上都是强引⽤,这是使⽤最普遍的引⽤。如果⼀个对象具有强引⽤,那就类似于必不可少的⽣活⽤品,垃圾回收器绝不会回收它。当内存空间不⾜,Java虚拟机宁愿抛出OutOfMemoryError错误,使程序异常终⽌,也不会靠随意回收具有强引⽤的对象来解决内存不⾜问题;
软引用:如果⼀个对象只具有软引⽤,那就类似于可有可⽆的⽣活⽤品。如果内存空间⾜够,垃圾回收器就不会回收它,如果内存空间不⾜了,就会回收这些对象的内存。只要垃圾回收器没有回收它,该对象就可以被程序使⽤;
弱引用:如果⼀个对象只具有弱引⽤,那就类似于可有可⽆的⽣活⽤品。弱引⽤与软引⽤的区别在于:只具有弱引⽤的对象拥有更短暂的⽣命周期。在垃圾回收器线程扫描它 所管辖的内存区域的过程中,⼀旦发现了只具有弱引⽤的对象,不管当前内存空间⾜够与否,都会回收它的内存。不过,由于垃圾回收器是⼀个优先级很低的线程, 因此不⼀定会很快发现那些只具有弱引⽤的对象;
虚引用:主要⽤来跟踪对象被垃圾回收的活动。
在程序设计中⼀般很少使⽤弱引⽤与虚引⽤,使⽤软引⽤的情况比较多,这是因为软引⽤可以加速JVM对垃圾内存的回收速度,可以维护系统的运⾏安全,防⽌内存溢出(OutOfMemory)等问题的产⽣。

垃圾回收算法

标记-清除算法
⾸先标记出所有需要回收的对象,在标记完成后统⼀回收所有被标记的对象。它是最基础的收集算法,后续的算法都是对其不⾜进⾏改进得到。这种垃圾收集算法会带来两个明显的问题:

  1. 效率问题
  2. 空间问题(标记清除后会产⽣⼤量不连续的碎⽚)

复制算法
为了解决效率问题,“复制”收集算法出现了。它可以将内存分为⼤⼩相同的两块,每次使⽤其中的⼀块。当这⼀块的内存使⽤完后,就将还存活的对象复制到另⼀块去,然后再把使⽤的空间⼀次清理掉。这样就使每次的内存回收都是对内存区间的⼀半进⾏回收。
标记-整理算法
根据⽼年代的特点特出的⼀种标记算法,标记过程仍然与“标记-清除”算法⼀样,但后续步骤不是直接对可回收对象回收,⽽是让所有存活的对象向⼀端移动,然后直接清理掉端边界以外的内存。
分代收集算法
当前虚拟机的垃圾收集都采⽤分代收集算法,这种算法没有什么新的思想,只是根据对象存活周期的不同将内存分为⼏块。⼀般将java堆分为新⽣代和⽼年代,这样我们就可以根据各个年代的特点选择合适的垃圾收集算法。
⽐如在新生代中,每次收集都会有⼤量对象死去,所以可以选择复制算法,只需要付出少量对象的复制成本就可以完成每次垃圾收集。⽽老年代的对象存活⼏率是⽐较⾼的,⽽且没有额外的空间对它进⾏分配担保,所以我们必须选择“标记-清除”或“标记-整理”算法进⾏垃圾收集。

垃圾回收器

Serial收集器
Serial(串⾏)收集器收集器是最基本、历史最悠久的垃圾收集器了。这个收集器是⼀个单线程收集器了。它的 “单线程” 的意义不仅仅意味着它只会使⽤⼀条垃圾收集线程去完成垃圾收集⼯作,更重要的是它在进⾏垃圾收集⼯作的时候必须暂停其他所有的⼯作线程( “Stop The World”),直到它收集结束。
新⽣代采⽤复制算法,⽼年代采⽤标记-整理算法。
ParNew收集器
ParNew收集器其实就是Serial收集器的多线程版本。
新⽣代采⽤复制算法,⽼年代采⽤标记-整理算法。
Parallel Scavenge收集器

-XX:UseParallelGC
 使⽤Parallel收集器+ ⽼年代串⾏
-XX:UseParallelOldGC
 使⽤Parallel收集器+ ⽼年代并⾏

Parallel Scavenge收集器关注点是吞吐量(⾼效率的利⽤CPU)。CMS等垃圾收集器的关注点更多的是⽤户线程的停顿时间(提⾼⽤户体验)。所谓吞吐量就是CPU中⽤于运⾏⽤户代码的时间与CPU总消耗时间的⽐值。
新⽣代采⽤复制算法,⽼年代采⽤标记-整理算法。
Serial Old收集器
Serial收集器的⽼年代版本,它同样是⼀个单线程收集器。它主要有两⼤⽤途:⼀种⽤途是在JDK1.5以及以前的版本中与Parallel Scavenge收集器搭配使⽤,另⼀种⽤途是作为CMS收集器的后备⽅案。
Parallel Old收集器
Parallel Scavenge收集器的⽼年代版本。使⽤多线程和“标记-整理”算法。在注重吞吐量以及CPU资源的场合,都可以优先考虑 Parallel Scavenge收集器和Parallel Old收集器。
CMS收集器
CMS(Concurrent Mark Sweep)收集器是⼀种以获取最短回收停顿时间为⽬标的收集器。它⽽⾮常符合在注重⽤户体验的应⽤上使⽤。CMS收集器是HotSpot虚拟机第⼀款真正意义上的并发收集器,它第⼀次实现了让垃圾收集线程与⽤户线程(基本上)同时⼯作。
CMS收集器是⼀种 “标记-清除”算法实现的。
优点:并发收集、低停顿。
缺点:
1.对CPU资源敏感;
2.⽆法处理浮动垃圾;
3.它使⽤的回收算法-“标记-清除”算法会导致收集结束时会有⼤量空间碎⽚产⽣。
G1收集器
G1 (Garbage-First)是⼀款⾯向服务器的垃圾收集器,主要针对配备多颗处理器及⼤容量内存的机器,以极高概率满⾜GC停顿时间要求的同时,还具备⾼吞吐量性能特征。
并⾏与并发:G1能充分利⽤CPU、多核环境下的硬件优势,使⽤多个CPU(CPU或者CPU核⼼)来缩短Stop-The-World停顿时间。部分其他收集器原本需要停顿Java线程执⾏的GC动作,G1收集器仍然可以通过并发的⽅式让java程序继续执⾏。
分代收集:虽然G1可以不需要其他收集器配合就能独⽴管理整个GC堆,但是还是保留了分代的概念。
空间整合:与CMS的“标记–清理”算法不同,G1从整体来看是基于“标记整理”算法实现的收集
器;从局部上来看是基于“复制”算法实现的。
可预测的停顿:这是G1相对于CMS的另⼀个⼤优势,降低停顿时间是G1 和 CMS 共同的关注点,但G1 除了追求低停顿外,还能建⽴可预测的停顿时间模型,能让使⽤者明确指定在⼀个⻓度为M毫秒的时间⽚段内。
G1收集器在后台维护了⼀个优先列表,每次根据允许的收集时间,优先选择回收价值最⼤的Region(这也就是它的名字Garbage-First的由来)。这种使⽤Region划分内存空间以及有优先级的区域回收⽅式,保证了GF收集器在有限时间内可以尽可能⾼的收集效率(把内存化整为零)。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值