企业门户网站建设机构,旅游网站的建设的文献综述,热点 做网站和营销 我只服他,上海大众汽车网站哪家公司做的JVM面试突击班2
对象被判定为不可达对象之后就“死”了吗
对象的生命周期 创建阶段
#xff08;1#xff09;为对象分配存储空间
#xff08;2#xff09;开始构造对象
#xff08;3#xff09;从超类到子类对static成员进行初始化
#xff08;4#xff09;超类成…JVM面试突击班2
对象被判定为不可达对象之后就“死”了吗
对象的生命周期 创建阶段
1为对象分配存储空间
2开始构造对象
3从超类到子类对static成员进行初始化
4超类成员变量按顺序初始化递归调用超类的构造方法
5子类成员变量按顺序初始化子类构造方法调用并且一旦对象被创建并被分派给某些变量赋值这个对象的状态就切换到了应用阶段
应用阶段
1系统至少维护着对象的一个强引用Strong Reference
2所有对该对象的引用全部是强引用除非我们显式地使用了软引用Soft Reference、弱引用Weak Reference或虚引用Phantom Reference 引用的定义 1.我们的数据类型必须是引用类型 2.我们这个类型的数据所存储的数据必须是另外一块内存的起始地址 [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zwiw3GKW-1691043052393)(https://fynotefile.oss-cn-zhangjiakou.aliyuncs.com/fynote/fyfile/1463/1650279430028/3900ed8910404854b5595e3c9979bb80.png)] 引用 1.强引用 JVM内存管理器从根引用集合Root Set出发遍寻堆中所有到达对象的路径。当到达某对象的任意路径都不含有引用对象时对这个对象的引用就被称为强引用 2.软引用 软引用是用来描述一些还有用但是非必须的对象。对于软引用关联的对象在系统将于发生内存溢出异常之前将会把这些对象列进回收范围中进行二次回收。 当你去处理占用内存较大的对象 并且生命周期比较长的不是频繁使用的 问题软引用可能会降低应用的运行效率与性能。比如软引用指向的对象如果初始化很耗时或者这个对象在进行使用的时候被第三方施加了我们未知的操作。 3.弱引用 弱引用Weak Reference对象与软引用对象的最大不同就在于GC在进行回收时需要通过算法检查是否回收软引用对象而对于Weak引用对象 GC总是进行回收。因此Weak引用对象会更容易、更快被GC回收 4.虚引用 也叫幽灵引用和幻影引用为一个对象设置虚引用关联的唯一目的就是能在这个对象被回收时收到一个系统通知。也就是说,如果一个对象被设置上了一个虚引用,实际上跟没有设置引用没有任何的区别 软引用代码Demo
public class SoftReferenceDemo {public static void main(String[] args) {//。。。一堆业务代码Worker a new Worker();
//。。业务代码使用到了我们的Worker实例// 使用完了a将它设置为soft 引用类型并且释放强引用SoftReference sr new SoftReference(a);a null;
//这个时候他是有可能执行一次GC的System.gc();// 下次使用时if (sr ! null) {a (Worker) sr.get();System.out.println(a );} else {// GC由于内存资源不足可能系统已回收了a的软引用// 因此需要重新装载。a new Worker();sr new SoftReference(a);}}}弱引用代码Demo
public class WeakReferenceDemo {public static void main(String[] args) throws InterruptedException {//100M的缓存数据byte[] cacheData new byte[100 * 1024 * 1024];//将缓存数据用软引用持有WeakReferencebyte[] cacheRef new WeakReference(cacheData);System.out.println(第一次GC前 cacheData);System.out.println(第一次GC前 cacheRef.get());//进行一次GC后查看对象的回收情况System.gc();//因为我们不确定我们的System什么时候GCThread.sleep(1000);System.out.println(第一次GC后 cacheData);System.out.println(第一次GC后 cacheRef.get());//将缓存数据的强引用去除cacheData null;System.gc(); //默认通知一次Full GC//等待GCThread.sleep(500);System.out.println(第二次GC后 cacheData);System.out.println(第二次GC后 cacheRef.get());// // 弱引用Map
// WeakHashMapString, String whm new WeakHashMapString,String();}
}
虚引用代码Demo
public class PhantomReferenceDemo {public static void main(String[] args) throws InterruptedException {Object value new Object();ReferenceQueueObject referenceQueue new ReferenceQueue();Thread thread new Thread(() - {try {int cnt 0;WeakReferencebyte[] k;while ((k (WeakReference) referenceQueue.remove()) ! null) {System.out.println((cnt) 回收了: k);}} catch (InterruptedException e) {//结束循环}});thread.setDaemon(true);thread.start();MapObject, Object map new HashMap();for (int i 0; i 10000; i) {byte[] bytes new byte[1024 * 1024];WeakReferencebyte[] weakReference new WeakReferencebyte[](bytes, referenceQueue);map.put(weakReference, value);}System.out.println(map.size- map.size());}
}finalize方法代码Demo
public class Finalize {private static Finalize save_hook null;//类变量public void isAlive() {System.out.println(我还活着);}Overridepublic void finalize() {System.out.println(finalize方法被执行);Finalize.save_hook this;}public static void main(String[] args) throws InterruptedException {save_hook new Finalize();//对象//对象第一次拯救自己save_hook null;System.gc();//暂停0.5秒等待他Thread.sleep(500);if (save_hook ! null) {save_hook.isAlive();} else {System.out.println(好了现在我死了);}//对象第二次拯救自己save_hook null;System.gc();//暂停0.5秒等待他Thread.sleep(500);if (save_hook ! null) {save_hook.isAlive();} else {System.out.println(我终于死亡了);}}
}不可见阶段
不可见阶段的对象在虚拟机的对象根引用集合中再也找不到直接或者间接的强引用最常见的就是线程或者函数中的临时变量。程序不在持有对象的强引用。 但是某些类的静态变量或者JNI是有可能持有的
不可达阶段
指对象不再被任何强引用持有GC发现该对象已经不可达。
引用 - 对象
如何确定一个对象是垃圾 要想进行垃圾回收得先知道什么样的对象是垃圾。 引用计数法 循环引用
对于某个对象而言只要应用程序中持有该对象的引用就说明该对象不是垃圾如果一个对象没有任何指针对其引用它就是垃圾。
弊端:如果AB相互持有引用导致永远不能被回收。 循环引用 内存泄露 --内存溢出 可达性分析/根搜索算法
通过GC Root的引用开始向下寻找看某个对象是否可达
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PhMt8Ze1-1691043052394)(file://E:/%E6%A1%8C%E9%9D%A2/yzt/%E7%AC%94%E8%AE%B0%E8%AF%BE%E4%BB%B6/JVM/3%E5%A4%A9JVM%E8%AE%AD%E7%BB%83%E8%90%A5/%E8%B5%84%E6%96%99%E7%AC%94%E8%AE%B0/images/64.png?lastModify1646659177)] 能作为GC Root:类加载器、Thread、虚拟机栈的本地变量表、static成员、常量引用、本地方法栈的变量等。 虚拟机栈栈帧中的本地变量表中引用的对象。
方法区中类静态属性引用的对象。
方法区中常量引用的对象。
本地方法栈中JNI即一般说的Native方法引用的对象。垃圾收集算法 已经能够确定一个对象为垃圾之后接下来要考虑的就是回收怎么回收呢得要有对应的算法下面介绍常见的垃圾回收算法。高效 健壮 标记-清除(Mark-Sweep)
标记
找出内存中所有的存活对象并且把它们标记出来
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Dhjmltab-1691043052395)(file://E:\桌面\yzt\笔记课件\JVM\3天JVM训练营\资料笔记\images\25.png?lastModify1646720640)]
清除
清除掉被标记需要回收的对象释放出对应的内存空间
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8GNPP7eo-1691043052396)(file://E:\桌面\yzt\笔记课件\JVM\3天JVM训练营\资料笔记\images\26.png?lastModify1646720640)][外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XDvs6uy2-1691043052396)(https://fynotefile.oss-cn-zhangjiakou.aliyuncs.com/fynote/1463/1646137467048/5beab74efce64c5897d16f39db5e58f3.png)]
缺点
标记清除之后会产生大量不连续的内存碎片空间碎片太多可能会导致以后在程
序运行过程中需要分配较大对象时无法找到足够的连续内存而不得不提前触发另一次垃圾收集动作。
(1)标记和清除两个过程都比较耗时效率不高
(2)会产生大量不连续的内存碎片空间碎片太多可能会导致以后在程序运行过程中需要分配较大对象时无法找到足够的连续内存而不得不提前触发另一次垃圾收集动作。标记清除算法的衍生规则之分配动态分区分配策略
首次适应算法Fisrt-fit
首次适应算法Fisrt-fit就是在遍历空闲链表的时候一旦发现有大小大于等于需要的大小之后就立即把该块分配给对象并立即返回。
最佳适应算法Best-fit
最佳适应算法Best-fit就是在遍历空闲链表的时候返回刚好等于需要大小的块。
最差适应算法Worst-fit
最差适应算法Worst-fit就是在遍历空闲链表的时候找出空闲链表中最大的分块将其分割给申请的对象其目的就是使得分割后分块的最大化以便下次好分配不过这种分配算法很容易产生很多很小的分块这些分块也不能被使用
什么是STWstop the world
Stop-The-World 简称 STW
是在垃圾回收算法执行过程中,将jvm内存冻结,停顿的一种状态在Stw情况下容易出现两种现象
该回收的对象没有被回收
不该回收的对象被回收了
在STW状态下,所有的线程都是停止运行的 - 垃圾回收线程除外
当STW发生时,出了GC所需要的线程,其他的线程都将停止工作,中断了的线程知道GC线程结束才会继续任务
STW是不可避免的,垃圾回收算法的执行一定会出现STW,而我们最好的解决办法就是减少停顿的时间
GC各种算法的优化重点就是为了减少STW,这也是JVM调优的重点。
标记-复制(Mark-Copying)
将内存划分为两块相等的区域每次只使用其中一块如下图所示
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5vmyhM0q-1691043052396)(file://E:\桌面\yzt\笔记课件\JVM\3天JVM训练营\资料笔记\images\27.png?lastModify1646720640)][外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BBFjF1XJ-1691043052397)(https://fynotefile.oss-cn-zhangjiakou.aliyuncs.com/fynote/1463/1646137467048/44cbc243638f4544917f0aa44e440c82.png)]
当其中一块内存使用完了就将还存活的对象复制到另外一块上面然后把已经使用过的内存空间一次清除掉。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LsB0KV8W-1691043052397)(file://E:\桌面\yzt\笔记课件\JVM\3天JVM训练营\资料笔记\images\28.png?lastModify1646720640)][外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-M4VX5JCx-1691043052397)(https://fynotefile.oss-cn-zhangjiakou.aliyuncs.com/fynote/1463/1646137467048/b81f9e21abd84b0aaa102f27c4007986.png)]
缺点:空间利用率降低。
标记-整理(Mark-Compact) 复制收集算法在对象存活率较高时就要进行较多的复制操作效率将会变低。更关键的是如果不想浪费50%的空间就需要有额外的空间进行分配担保以应对被使用的内存中所有对象都有100%存活的极端情况所以老年代一般不能直接选用这种算法。 标记过程仍然与标记-清除算法一样但是后续步骤不是直接对可回收对象进行清理而是让所有存活的对象都向一端移动然后直接清理掉端边界以外的内存。 其实上述过程相对复制算法来讲少了一个保留区 [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-u0NeLjuW-1691043052398)(file://E:\桌面\yzt\笔记课件\JVM\3天JVM训练营\资料笔记\images\25.png?lastModify1646720640)][外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-foAjps2M-1691043052398)(https://fynotefile.oss-cn-zhangjiakou.aliyuncs.com/fynote/1463/1646137467048/331b1e9000d34b5093ed5b60a24e0402.png)]
让所有存活的对象都向一端移动清理掉边界意外的内存。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AhU6RCfJ-1691043052398)(file://E:\桌面\yzt\笔记课件\JVM\3天JVM训练营\资料笔记\images\29.png?lastModify1646720640)]
分代收集算法 既然上面介绍了3中垃圾收集算法那么在堆内存中到底用哪一个呢 Young区复制算法(对象在被分配之后可能生命周期比较短Young区复制效率比较高)
Old区标记清除或标记整理(Old区对象存活时间比较长复制来复制去没必要不如做个标记再清理)
其他算法
增量回收算法
垃圾回收其实就是对不需要的内存对象进行清理前面提到的GC算法无论哪种基本都是过一段时间对所有的内存空间对象进行一次大扫除。 这种的GC缺点是一旦开始启动管理程序可能就停止了表现就是可能好多程序都没响应。可在服务端这是大忌。增量式incremental出现就是解决这个问题的这种垃圾回收采用和应用程序交替进行的方式来工作表现就像是GC在不断的定时迭加操作。从而尽量减轻应用程序的停止时间这就是增量式回收的特点。 在增量式回收里比较容易接触到的就是三色标记算法。
三色标记
在并发标记的过程中因为标记期间应用线程还在继续跑对象间的引用可能发生变化多标和漏标的情况就有可能发生。这里引入“三色标记”来给大家解释下把Gc roots可达性分析遍历对象过程中遇到的对象 按照“是否访问过”这个条件标记成以下三种颜色
黑色
表示对象已经被垃圾收集器访问过 且这个对象的所有引用都已经扫描过。 黑色的对象代表已经扫描过 它是安全存活的 如果有其他对象引用指向了黑色对象 无须重新扫描一遍。 黑色对象不可能直接不经过灰色对象 指向某个白色对象。2.将GC Roots 直接引用到的对象 挪到 【灰色集合】中
3.从灰色集合中获取对象
将本对象 引用到的 其他对象 全部挪到 【灰色集合】中将本对象 挪到 【黑色集合】里面。
重复步骤3.4直至【灰色集合】为空时结束。
结束后仍在【白色集合】的对象即为GC Roots 不可达可以进行回收 多标-浮动垃圾
在并发标记过程中如果由于方法运行结束导致部分局部变量(gcroot)被销毁这个gc root引用的对象之前又被扫描过 (被标记为非垃圾对象)那么本轮GC不会回收这部分内存。这部分本应该回收但是没有回收到的内存被称之为“浮动 垃圾”。浮动垃圾并不会影响垃圾回收的正确性只是需要等到下一轮垃圾回收中才被清除。另外针对并发标记(还有并发清理)开始后产生的新对象通常的做法是直接全部当成黑色本轮不会进行清除。这部分 对象期间可能也会变为垃圾这也算是浮动垃圾的一部分。漏标-读写屏障
漏标只有同时满足以下两个条件时才会发生
条件一灰色对象 断开了 白色对象的引用即灰色对象 原来成员变量的引用 发生了变化。条件二黑色对象 重新引用了 该白色对象即黑色对象 成员变量增加了 新的引用。漏标会导致被引用的对象被当成垃圾误删除这是严重bug必须解决有两种解决方案 增量更新Incremental Update 和原始快照Snapshot At The BeginningSATB 。
增量更新就是当黑色对象插入新的指向白色对象的引用关系时 就将这个新插入的引用记录下来 等并发扫描结束之后 再将这些记录过的引用关系中的黑色对象为根 重新扫描一次。 这可以简化理解为 黑色对象一旦新插入了指向白色对象的引用之后 它就变回灰色对象了。
原始快照就是当灰色对象要删除指向白色对象的引用关系时 就将这个要删除的引用记录下来 在并发扫描结束之后 再将这些记录过的引用关系中的灰色对象为根 重新扫描一次这样就能扫描到白色的对象将白色对象直接标记为黑色(目的就是让这种对象在本轮gc清理中能存活下来待下一轮gc的时候重新扫描这个对象也有可能是浮动垃圾)
以上无论是对引用关系记录的插入还是删除 虚拟机的记录操作都是通过写屏障实现的。
写屏障实现原始快照SATB 当对象B的成员变量的引用发生变化时比如引用消失a.b.d null我们可以利用写屏障将B原来成员变量的引用对象D记录下来
写屏障实现增量更新 当对象A的成员变量的引用发生变化时比如新增引用a.d d我们可以利用写屏障将A新的成员变量引用对象D 记录下来
垃圾收集器 如果说收集算法是内存回收的方法论那么垃圾收集器就是内存回收的具体实现。 [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wLbYuq97-1691043052399)(file://E:\桌面\yzt\笔记课件\JVM\3天JVM训练营\资料笔记\images\30.png?lastModify1646736013)]
Serial
Serial收集器是最基本、发展历史最悠久的收集器曾经在JDK1.3.1之前是虚拟机新生代收集的唯一选择。
它是一种单线程收集器不仅仅意味着它只会使用一个CPU或者一条收集线程去完成垃圾收集工作更重要的是其在进行垃圾收集的时候需要暂停其他线程。
优点简单高效拥有很高的单线程收集效率
缺点收集过程需要暂停所有线程
算法复制算法
适用范围新生代
应用Client模式下的默认新生代收集器[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Gzasijoi-1691043052399)(file://E:\桌面\yzt\笔记课件\JVM\3天JVM训练营\资料笔记\images\31.png?lastModify1646736013)]
Serial Old
Serial Old收集器是Serial收集器的老年代版本也是一个单线程收集器不同的是采用标记-整理算法运行过程和Serial收集器一样。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wS3WqK7d-1691043052400)(file://E:\桌面\yzt\笔记课件\JVM\3天JVM训练营\资料笔记\images\32.png?lastModify1646736013)]
ParNew
可以把这个收集器理解为Serial收集器的多线程版本。
优点在多CPU时比Serial效率高。
缺点收集过程暂停所有应用程序线程单CPU时比Serial效率差。
算法复制算法
适用范围新生代
应用运行在Server模式下的虚拟机中首选的新生代收集器[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-e6AcUdZX-1691043052401)(file://E:\桌面\yzt\笔记课件\JVM\3天JVM训练营\资料笔记\images\33.png?lastModify1646736013)]
Parallel Scavenge
Parallel Scavenge收集器是一个新生代收集器它也是使用复制算法的收集器又是并行的多线程收集器看上去和ParNew一样但是Parallel Scanvenge更关注系统的吞吐量。 吞吐量运行用户代码的时间/(运行用户代码的时间垃圾收集时间) 比如虚拟机总共运行了100分钟垃圾收集时间用了1分钟吞吐量(100-1)/10099%。 若吞吐量越大意味着垃圾收集的时间越短则用户代码可以充分利用CPU资源尽快完成程序的运算任务。 -XX:MaxGCPauseMillis控制最大的垃圾收集停顿时间
-XX:GCRatio直接设置吞吐量的大小。Parallel Old
Parallel Old收集器是Parallel Scavenge收集器的老年代版本使用多线程和标记-整理算法进行垃圾回收也是更加关注系统的吞吐量。
CMS 官网 https://docs.oracle.com/javase/8/docs/technotes/guides/vm/gctuning/cms.html#concurrent_mark_sweep_cms_collector CMS(Concurrent Mark Sweep)收集器是一种以获取 最短回收停顿时间为目标的收集器。 采用的是标记-清除算法,整个过程分为4步 (1)初始标记 CMS initial mark 标记GC Roots直接关联对象不用Tracing速度很快
(2)并发标记 CMS concurrent mark 进行GC Roots Tracing
(3)重新标记 CMS remark 修改并发标记因用户程序变动的内容
(4)并发清除 CMS concurrent sweep 清除不可达对象回收空间同时有新垃圾产生留着下次清理称为浮动垃圾由于整个过程中并发标记和并发清除收集器线程可以与用户线程一起工作所以总体上来说CMS收集器的内存回收过程是与用户线程一起并发地执行的。 [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fBwaGKey-1691043052403)(file://E:\桌面\yzt\笔记课件\JVM\3天JVM训练营\资料笔记\images\34.png?lastModify1646736013)]
优点并发收集、低停顿
缺点产生大量空间碎片、并发阶段会降低吞吐量
什么是记忆集
当我们进行young gc时我们的gc roots除了常见的栈引用、静态变量、常量、锁对象、class对象这些常见的之外如果 老年代有对象引用了我们的新生代对象 那么老年代的对象也应该加入gc roots的范围中但是如果每次进行young gc我们都需要扫描一次老年代的话那我们进行垃圾回收的代价实在是太大了因此我们引入了一种叫做记忆集的抽象数据结构来记录这种引用关系。
记忆集是一种用于记录从非收集区域指向收集区域的指针集合的数据结构。
如果我们不考虑效率和成本问题我们可以用一个数组存储所有有指针指向新生代的老年代对象。但是如果这样的话我们维护成本就很好打个比方假如所有的老年代对象都有指针指向了新生代那么我们需要维护整个老年代大小的记忆集毫无疑问这种方法是不可取的。因此我们引入了卡表的数据结构卡表
记忆集是我们针对于跨代引用问题提出的思想而卡表则是针对于该种思想的具体实现。可以理解为记忆集是结构卡表是实现类
[1字节000010001字节1字节]
在hotspot虚拟机中卡表是一个字节数组数组的每一项对应着内存中的某一块连续地址的区域如果该区域中有引用指向了待回收区域的对象卡表数组对应的元素将被置为1没有则置为0(1) 卡表是使用一个字节数组实现:CARD_TABLE[],每个元素对应着其标识的内存区域一块特定大小的内存块,称为卡页。hotSpot使用的卡页是2^9大小,即512字节
(2) 一个卡页中可包含多个对象,只要有一个对象的字段存在跨代指针,其对应的卡表的元素标识就变成1,表示该元素变脏,否则为0。GC时,只要筛选本收集区的卡表中变脏的元素加入GC Roots里。
卡表的使用图例 并发标记的时候A对象发生了所在的引用发生了变化所以A对象所在的块被标记为脏卡 继续往下到了重新标记阶段修改对象的引用同时清除脏卡标记。 卡表其他作用
老年代识别新生代的时候
对应的card table被标识为相应的值card table中是一个byte有八位约定好每一位的含义就可区分哪个是引用新生代哪个是并发标记阶段修改过的
G1(Garbage-First) 官网 https://docs.oracle.com/javase/8/docs/technotes/guides/vm/gctuning/g1_gc.html#garbage_first_garbage_collection **使用G1收集器时Java堆的内存布局与就与其他收集器有很大差别它将整个Java堆划分为多个大小相等的独立区域Region虽然还保留有新生代和老年代的概念但新生代和老年代不再是物理隔离的了它们都是一部分Region不需要连续的集合。 ** 每个Region大小都是一样的可以是1M到32M之间的数值但是必须保证是2的n次幂 如果对象太大一个Region放不下[超过Region大小的50%]那么就会直接放到H中 设置Region大小-XX:G1HeapRegionSizeM 所谓Garbage-Frist其实就是优先回收垃圾最多的Region区域 1分代收集仍然保留了分代的概念
2空间整合整体上属于“标记-整理”算法不会导致空间碎片
3可预测的停顿比CMS更先进的地方在于能让使用者明确指定一个长度为M毫秒的时间片段内消耗在垃圾收集上的时间不得超过N毫秒[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nqSjHkRk-1691043052413)(file://E:\桌面\yzt\笔记课件\JVM\3天JVM训练营\资料笔记\images\35.png?lastModify1646736013)]
工作过程可以分为如下几步
初始标记Initial Marking 标记以下GC Roots能够关联的对象并且修改TAMS的值需要暂停用户线程
并发标记Concurrent Marking 从GC Roots进行可达性分析找出存活的对象与用户线程并发执行
最终标记Final Marking 修正在并发标记阶段因为用户程序的并发执行导致变动的数据需暂停用户线程
筛选回收Live Data Counting and Evacuation 对各个Region的回收价值和成本进行排序根据用户所期望的GC停顿时间制定回收计划[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TidJQnXA-1691043052417)(file://E:\桌面\yzt\笔记课件\JVM\3天JVM训练营\资料笔记\images\36.png?lastModify1646736013)]
ZGC 官网 https://docs.oracle.com/en/java/javase/11/gctuning/z-garbage-collector1.html#GUID-A5A42691-095E-47BA-B6DC-FB4E5FAA43D0 JDK11新引入的ZGC收集器不管是物理上还是逻辑上ZGC中已经不存在新老年代的概念了 会分为一个个page当进行GC操作时会对page进行压缩因此没有碎片问题 只能在64位的linux上使用目前用得还比较少 1可以达到10ms以内的停顿时间要求
2支持TB级别的内存
3堆内存变大后停顿时间还是在10ms以内