回收算法:标记-清除mark-sweep,复制copy,标记-压缩mark-compact。
垃圾回收器:10种。
将内存分为2部分和多部分。
jdk1.8将内存分为2大年代,新生代和老年代。
①新生代:
刚刚诞生的对象优先分配给新生代。(刚new出来,年轻的对象)
eden区经过一次的垃圾回收,min或YGC。可清理90%清理掉,留下的放到survivor1
eden区+survivor1扫描,留下的放到survivor2.
eden区 -> survivor1 -> sruvivor2
比例: 8 -> 1 -> 1
【算法】:采用copy复制算法。
②老年代:
经历过垃圾回收的对象(对象经历过垃圾回收,年龄+1,超过一定年龄到老年代)。
内存装不下的时候再垃圾回收一次,清理。
【算法】:标记-清除,标记-压缩。或两者整合。
年轻代满了触发年轻代YGC,老年代满了出发FullGC。
③永久代 ,放class元数据用的。
JDK1.7之前叫perminent area,永久代。
JDK1.8之后叫Metaspace,元空间
都叫方法区。method area。
***********************************垃圾回收演化随着内存大小的不断增长而演进。
1、内存分代模型:
**内存大小几兆到几十兆。
①serial:STW copying collector,单线程GC。
工作在年轻代,业务线程全部停止,垃圾回收器开始清理垃圾。清理完成后,业务线程继续执行。
复制算法的单线程STW垃圾回收,年轻代 老年代。
②serialOld:工作在老年代,单线程STW,采用mark-sweep(标记-清除)算法。
**内存大小几十兆到上百兆或1G。
③parallel scavenge并行多线程,工作在年轻代。PS
④parallelOld并行多线程,工作在老年代。PO
JDK1.8采用的是PS+PO。parallel GC垃圾回收器。
怎么知道使用的是什么垃圾回收器,使用命令查看:
java -XX:+PrintCommandLineFlags -version
**内存大小1G到几十G。
问:是不是线程越多,效率越高?
答:否。线程到达一定阈值之后,效率会遍变低。
一核CPU只能处理一个线程。16核处理16个线程。线程撕裂者,4核8线程,8核16线程。
1W线程会出现排队和切换,切换本身消耗CPU资源的,线程多,上下文的切换contextSwitch,
线程切换所消耗的资源超过了线程运行所占的资源。效率反而会降低。
线程越多,会出现线程等待。
⑤CMS,工作在老年代。年轻代使用serial和parNew(工作在年轻代的多线程)。并发标记清除concurrent mark
CMS不能与PS配合使用的原因是PS不符合它的要求。
存在天生的bug。
**初始标记(找到root根对象,STW时间短)、
**并发标记(三色标记算法,业务线程执行的同时进行并发标记,会出现错标)、
**重新标记(修复标记,STW时间短)、
**并发清理。
Golang采用三色标记算法。
【三色标记算法】:
场景是在并发标记阶段,垃圾回收线程是间隔一段时间运行。每次记录当前标记的位置,Linux采用CFS算法(完全公平算法,不是平均分配),垃圾回收线程运行后记录标记位置。
a.标记追踪对象过程中,已完成追踪到对象和子节点,标记黑色(再次扫描不再标记黑对象)
b.子节点对象非垃圾,已扫描完成,但子子对象还没标记,标记为灰色
c.还没遍历到的节点标记为白对象。
颜色标记放在mark word中。
8字节mark word:锁信息、哈希code、GC(CMS的head记录在此)
4字节classpointer
n个字节的instance state
n个字节的padding
第一种情况:B-D的引用消失。浮动垃圾。无影响,下一次扫描会被标记垃圾。
B->D引用消失,A-D引用增加。D扫描不到,会出现误删情况。
CMS解决方案,把黑色修正为灰色。incremental update(有bug,导致漏标)。依然会产生漏标。
CMS的remak重新标记,还是从头扫描一遍。
⑥parNew
工作在年轻代,多线程。并发标记清除。
⑦G1
JDK1.7与CMS同样,算法不同,采用SATB算法,解决漏标bug。
G1摒弃了年轻代和老年代,内存越来越大,量大处理不来。
物理不分代,逻辑分代。内存区域不固定。
分区算法region。部分回收,连续内存humongous。G1的fullGC。
缺点:一次回收要把年轻代全部回收。YGC全部回收,STW时间长。
⑧ZGC
oracle支持,分页算法,颜色指针colord pointer + 负载屏障load barrier。
不再分年轻代和老年代。每100ms触发一次GC,满的区域回收掉。
⑨Shenandoah
JDK12引入的垃圾回收器,redhat开发的开源。类似ZGC,分页算法。
⑩epsilon
JDK11 版本引入的,什么都不干垃圾回收器。只做记录和跟踪,开发JVM debug使用。
CMS、G1、ZGC、Shenandoah,都使用concurrent GC垃圾回收器。
GC线程和业务线程可以同时运行。
2、内存不分代模型