java垃圾回收知识总结

垃圾回收:

将已经分配出去的内存,取不再使用的回收回来,已便于再次分配

 

如何区分对象是否变成垃圾?

 

引用计数法与可达性分析

引用计数法:

使用计数器统计对象引用个数

 

使用语言:

Python

 

问题:

需要额外的空间存储计数器,频繁更新操作

无法处理循环引用问题

 

可达性分析:

GCRoot作为初始存活对象合集

 

GCRoot:

堆外指向堆内的引用

 

GCRoot范围:

Java方法栈帧中的局部变量

已加载类的静态变量

JNI handles

已启动且未停止的Java线程

 

好处:

解决了循环引用问题

 

问题:

多线程情况下可能出现漏报和误报

 

Stop-the-world以及安全点

解决方案:

STW(Stop the World),停止其他非垃圾回收的工作,直到垃圾回收完成,这一段时间会造成GC暂停。

通过安全点机制来实现STW,当所有线程都到达安全点,才准许STW独占线程工作。

安全点的作用,找到一个稳定状态,jvm不在产生堆栈。

 

垃圾回收的三种方式

标记-清除:

原理及其简单,造成内存碎片,分配效率低

821deec294f95447d020a791be1f134a31e.jpg

标记-压缩:

解决内存碎片化问题,代价压缩算法性能开销

d714662a206e158d0c4a8d6e98325bb39b2.jpg

标记-复制:

同样能解决内存碎片化问题,缺点堆空间使用效率低下

d55ed01489f7d0c50858e627c866bba2bca.jpg

bcd346e863584cb5e8795187f6dcbe31a5e.jpg

 

JVM虚拟机的堆划分

JVM通过分代思想进行垃圾回收,JVM堆分为新生代和老年代。

新生代:

Eden区以及两个大小相同的Survivor区

Eden存储对象的内存,对空间是线程共享,因此划分空间是需要同步。

通过TLAB避免两个对象共用一段内存。

TLAB可以向JVM申请一段连续的内存为线程私有。

 

申请操作需要加锁Eden区内存耗尽怎么办?

JVM便会触发Minor GC,存活对象放置到Survivor区。

from指针的survivor区中的对象会复制到to指向的Survivor区。

交换from和to指针,下次Minor GC时,to指向的survivor区还是空的。

如果JVM对象在survivor区复制默认超过15次晋升到老年代,或者单个survivor区已占用50%,较高复制次数的对象也会晋升到老年代。

 

MinorGC好处不会对整个堆进行垃圾回收。

但是有一个问题,老年代的对象可能引用新生代的对象。

在标记存活对象时,我们需要扫描老年代的对象。

如果该对象拥有对新生代对象的引用,这个也会被作为GCRoots。

可能会导致重新做一次全堆扫描,引入了卡表技术

 

卡表

卡表(Card Table):

将整个堆分为一个个大小为512字节的卡,并且维护一个卡表,用来存储每张卡的一个标识位。

这个标识位代表对象的卡是否可能存在指向新生代对象的引用。如果存在,我们认为这张卡是脏卡。

633467b2bf645cfd342ae1eb8134a7b826f.jpg

 

如何设置卡的标识位?

JVM获取每个引用型实例的写操作,并记录写标识位的操作

解释执行实现简单。JIT则需要插入额外逻辑,写屏障(write barrier)。

写屏障:

能加大Minor GC的效率,但是会带来虚共享问题,可以通过-XX:UseCondCardMark,来尽量减少写卡表的操作

 

垃圾回收器类型

Serial:

最古老、最稳定的垃圾回收器

可同时作用于新生代和老年代

新生代采用复制算法

老年代采用标记-压缩算法

 

ParNew:

Serial收集器新生代的并行版本

复制算法

多线程,需多核支持

-XX:ParallelGCThreads限制线程数量

 

Parallel收集器:

类似ParNew,

新生代复制算法,老年代标记压缩

更加关注吞吐量

-XX:+UseParallelGC使用Parallel收集器+老年代串行

-XX:+UseParallelOldGC使用Parallel收集器+老年代并行

-XX:+MaxGCPauseMills最大停顿时间,单位毫秒,GC尽量保证回收不超过该时间

-XX:+GCTimeRatio 0-100的取值范围,垃圾收集时间占总时间的比,默认99,即最大允许1%时间做GC

 TIPS:停顿时间和吞吐量不可能同时调优

 

CMS收集器:

Concurrent Mark Sweep并发标记清除

标记清除算法

并发阶段降低吞吐量

老年代收集器(新生代使用ParNew)

-XX:+UseConcMarkSweepGC

 

G1收集器:

横跨新生代和老年代

打乱堆结构,堆分成很多个区域,每个区域都可以充当Eden区、Survivor区或者老年代其中一个

标记压缩算法

G1在Java7中发布取代CMS, java9以后CMS收集器废弃

优先回收死亡对象较多的区域

 

ZGC收集器:

暂停时间不超过10ms

java11将提供

转载于:https://my.oschina.net/u/1017791/blog/3033995

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值