数哥:今天 05-20 据说这是一个节日?
我:不知道
数哥:那你今天怎么过?
我:撸起袖子-撸代码
描述:
优点:
缺点:
描述:
优点:
缺点:
描述:
优点:
缺点:
分代算法主要就是基于以上三种算法 ”因才施教“;
不同的区域使用 适合的算法;
具体的各种垃圾收集器 就是很好的实现
1、用于新生代
2、使用复制算法
3、单线程运行-进行垃圾收集时,暂停所有工作线程,即"Stop The World"
1、用于老年代
2、使用标记整理算法
3、单线程运行-进行垃圾收集时,暂停所有工作线程,即"Stop The World"
时序图
设置:"-XX:+UseSerialGC":添加该参数来显式的使用串行垃圾收集器;
参数设置:
“-XX:+UseParNewGC”:强制指定使用ParNew;
“-XX:ParallelGCThreads”:指定垃圾收集的线程数量,ParNew默认开启的收集线程与CPU的数量相同;
Parallel Scavenge收集器类似ParNew收集器,Parallel收集器更关注系统的吞吐量;新生代使用"复制"算法,老年代使用"标记-压缩"
Parallel Old是Parallel Scavenge收集器的老年代版本,使用多线程和"标记压缩"算法
参数设置:
-XX:+UseParallelGC 使用Parallel收集器+老年代串行
-XX:+UseParallelOldGC 使用Parallel收集器+老年代并行
CMS(Concurrent Mark Sweep)收集器是一种以获取最短回收停顿时间为目标的收集器;
老年代收集器(新生代使用ParNew)老年代收集器(新生代使用ParNew);
初始标记、重新标记这两个步骤仍然需要"Stop The World";
优点:并发收集、低停顿
缺点:产生大量空间碎片、并发阶段会降低吞吐量
参数设置:
-XX:+UseConcMarkSweepGC 使用CMS收集器
-XX:+UseCMSCompactAtFullCollection "Full GC"后,进行一次碎片整理,整理过程是独占的,会引起停顿时间变长
-XX:+CMSFullGCsBeforeCompaction 设置进行几次Full GC后,进行一次碎片整理
-XX:ParallelCMSThreads 设定CMS的线程数量(一般情况约等于可用CPU数量)
G1收集器有以下特点:
与其他垃圾收集器的区别:
上面提到的垃圾收集器,收集的范围都是整个新生代或者老年代;使用G1收集器时,Java堆的内存布局与其他收集器有很大差别,它将整个Java堆划分为多个大小相等的独立区域(Region),虽然还保留有新生代和老年代的概念,新生代和老年代不再是物理隔阂,它们都是一部分(可以不连续)Region的集合
收集步骤:
在JDK 11当中,加入了实验性质的ZGC。它的回收耗时平均不到2毫秒。它是一款低停顿高并发的收集器。
ZGC几乎在所有地方并发执行的,除了初始标记的是STW的。所以停顿时间几乎就耗费在初始标记上,这部分的实际是非常少的。那么其他阶段是怎么做到可以并发执行的呢?
ZGC主要新增了两项技术,一个是着色指针Colored Pointer,另一个是读屏障Load Barrier。
着色指针Colored Pointer
ZGC利用指针的64位中的几位表示Finalizable、Remapped、Marked1、Marked0(ZGC仅支持64位平台),以标记该指向内存的存储状态。相当于在对象的指针上标注了对象的信息。注意,这里的指针相当于Java术语当中的引用。
在这个被指向的内存发生变化的时候(内存在Compact被移动时),颜色就会发生变化。
在G1的时候就说到过,Compact阶段是需要STW,否则会影响用户线程执行。那么怎么解决这个问题呢?
读屏障Load Barrier 由于着色指针的存在,在程序运行时访问对象的时候,可以轻易知道对象在内存的存储状态(通过指针访问对象),若请求读的内存在被着色了。那么则会触发读屏障。读屏障会更新指针再返回结果,此过程有一定的耗费,从而达到与用户线程并发的效果。
新生代 | 老年代 |
---|---|
Serial | Serial Old |
Serial | CMS + Serial Old |
ParNew | CMS |
ParNew | Serial Old |
Parallel Scavenge | Serial Old |
Parallel Scavenge | Parallel Old |
G1 | G1 |
个人水平有限,如有问题,欢迎大家留言指出,虚心接受,及时更正
如果大家觉得,还可以,烦请点赞收藏,谢谢