大连哪家公司做网站好,自己注册了个域名想做一个网站吗,怎样免费做网站视频讲解,创建直播平台专栏导航 JVM工作原理与实战 RabbitMQ入门指南 从零开始了解大数据 目录
专栏导航
前言
一、垃圾回收算法介绍
1.垃圾回收算法的历史和分类
2.垃圾回收算法的评价标准
二、垃圾回收算法详解
1.标记清除算法
2.复制算法
3.标记整理算法
4.分代垃圾回收算法
总结 前言… 专栏导航 JVM工作原理与实战 RabbitMQ入门指南 从零开始了解大数据 目录
专栏导航
前言
一、垃圾回收算法介绍
1.垃圾回收算法的历史和分类
2.垃圾回收算法的评价标准
二、垃圾回收算法详解
1.标记清除算法
2.复制算法
3.标记整理算法
4.分代垃圾回收算法
总结 前言
JVM作为Java程序的运行环境其负责解释和执行字节码管理内存确保安全支持多线程和提供性能监控工具以及确保程序的跨平台运行。本文主要介绍了垃圾回收算法评价标准、标记清除算法、复制算法、标记整理算法、分代垃圾回收算法等内容。 一、垃圾回收算法介绍
垃圾回收算法在Java中起到了至关重要的作用它的主要任务是自动管理内存避免内存泄漏和垃圾堆积。那么Java是如何实现垃圾回收的呢简单来说垃圾回收要做的有两件事
找到内存中存活的对象这部分的任务主要是通过“标记”过程来完成。在Java中所有的对象都由引用进行连接如果一个对象没有任何引用指向它那么它就被认为是不可达的也就是死亡对象。标记阶段就是通过遍历所有的对象找出并标记那些被引用的对象从而确定哪些对象仍然存活。释放不再存活对象的内存这部分的任务主要是通过“清除”过程来完成。一旦标记阶段确定了哪些对象是存活那么所有未被标记的对象就被认为是不可达的它们的内存就可以被安全地释放以便程序能再次利用这部分空间。
1.垃圾回收算法的历史和分类
自1960年起John McCarthy首次提出了标记-清除算法Mark Sweep GC标志着垃圾回收算法的诞生。随后1963年Marvin L. Minsky引入了复制算法Copying GC这两种算法成为后续垃圾回收算法的基础。在此基础上垃圾回收算法不断发展出现了标记-整理算法Mark Compact GC、分代GCGenerational GC等优化版本。这些算法在实现垃圾回收的过程中均致力于提高内存利用率降低停顿时间以满足不同应用场景的需求。
2.垃圾回收算法的评价标准
在Java中垃圾回收通过独立的GC线程完成但无论采用何种GC算法都会存在需要暂停所有用户线程的阶段。这一过程被称为“Stop-The-World”STW。如果该过程过长将对用户体验产生负面影响。因此评价垃圾回收算法的优劣需基于以下三个关键标准
吞吐量吞吐量指的是 CPU 用于执行用户代码的时间与 CPU 总执行时间的比值即吞吐量 执行用户代码时间 / 执行用户代码时间 GC时间。吞吐量数值越高垃圾回收的效率就越高。比如虚拟机总共运行了 100 分钟其中GC花掉 1 分钟那么吞吐量就是 99%。最大暂停时间最大暂停时间指的是所有在垃圾回收过程中的STWStop The World时间最大值。STW是垃圾回收过程中需要停止所有的用户线程的时间。最大暂停时间越短用户使用系统时受到的影响就越短。堆使用效率不同垃圾回收算法对堆内存的使用方式是不同的。比如标记清除算法可以使用完整的堆内存。而复制算法会将堆内存一分为二每次只能使用一半内存。从堆使用效率上来说标记清除算法要优于复制算法。
上述三种评价标准堆使用效率、吞吐量以及最大暂停时间不可兼得。一般来说堆内存越大最大暂停时间就越长。想要减少最大暂停时间就会降低吞吐量。不同的垃圾回收算法适用于不同的场景。
二、垃圾回收算法详解
1.标记清除算法
标记清除算法是垃圾回收中的一种基础算法其核心思想分为两个阶段标记阶段和清除阶段。
标记阶段在标记阶段算法通过可达性分析从GC Root垃圾回收起始点开始通过引用链遍历出所有存活的对象。清除阶段在清除阶段算法从内存中删除未被标记的对象即非存活对象。
标记清除算法的优点
只需要在标记阶段给每个对象维护一个标记位然后在清除阶段删除未被标记的对象即可。
标记清除算法的缺点
内存碎片化问题由于内存是连续的当对象被删除后内存中会出现许多细小的可用内存单元。如果需要分配一个较大的空间这些小内存单元可能无法满足需求导致内存浪费和碎片化。分配速度慢由于内存碎片的存在需要维护一个空闲链表。在分配内存时可能需要遍历整个链表才能找到合适的空闲内存空间导致分配速度变慢。
尽管标记清除算法存在一些缺陷但它仍广泛应用于垃圾回收的实现中。在许多情况下通过与其他算法结合使用可以克服其缺点并提高垃圾回收的效率和性能。
2.复制算法
复制算法是一种垃圾回收算法其核心思想是将堆内存分为两个相同的空间即From空间和To空间。在对象分配阶段只能使用其中一个空间通常是From空间。在垃圾回收阶段存活的对象被复制到另一个未使用的空间To空间。完成复制后两个空间的角色互换原先的From空间变成To空间而原先的To空间变成新的From空间。
完整的复制算法执行过程如下
将整个堆内存分割成两个等大的空间即From空间和To空间。在对象分配阶段新创建的对象只能在From空间中分配。当垃圾回收阶段开始时所有从GC Root开始的存活对象将被复制到To空间中。接着将GC Root及其关联的对象也复制到To空间中。最后清理From空间中的所有对象并将两个空间的名称互换。 案例 将整个堆内存分割成两个等大的空间即From空间和To空间。在对象分配阶段新创建的对象只能在From空间中分配。 当垃圾回收阶段开始时所有从GC Root开始的存活对象将被复制到To空间中接着将GC Root及其关联的对象也复制到To空间中。 清理From空间中的所有对象并将两个空间的名称互换。 复制算法的优点
吞吐量高由于只需要遍历一次存活对象并将其复制到To空间因此性能较好。相比之下标记-整理算法需要两次遍历过程标记-清除算法不需要移动对象。不会发生内存碎片化由于在复制后对象按顺序放置在To空间中因此对象以外的区域都是可用空间不存在内存碎片化问题。
复制算法的缺点
内存使用效率低由于每次只能使用一半的内存空间来创建对象因此内存利用率相对较低。这意味着在其他算法可以处理更多对象时复制算法可能会浪费一半的内存空间。
3.标记整理算法
标记整理算法也被称为标记压缩算法旨在解决标记清除算法中容易出现的内存碎片化问题。其核心思想分为两个阶段
标记阶段这个阶段与标记清除算法中的标记阶段类似。通过可达性分析从GC Root开始遍历引用链以标记所有存活的对象。整理阶段在这一阶段所有存活的对象被移动到堆内存的一端。这有助于消除内存碎片并使内存空间连续可用。 案例 将所有存活的对象移动到堆内存的一端。 标记整理算法的优点
内存使用效率高整个堆内存都可以被充分利用不会像复制算法那样只能使用半个堆内存。防止内存碎片化由于在整理阶段将存活对象移动到堆的一侧剩余的空间可以连续地用于分配新对象从而避免了内存碎片化问题。
标记整理算法的缺点
整理阶段的效率问题虽然存在一些高效的整理算法如Two-Finger、表格算法、ImmixGC等但标记整理算法的整体性能可能不如复制算法或标记清除算法。例如某些实现可能需要遍历整个堆中的对象多次这可能导致性能瓶颈。
为了提高标记整理算法的性能可以采用一些优化策略。例如使用更高效的标记和整理算法或者结合其他垃圾回收算法如复制算法或分代收集算法来提高整体效率。通过合理的算法选择和优化可以更好地平衡垃圾回收的效率和内存使用效率。
4.分代垃圾回收算法
分代垃圾回收算法是一种优秀的垃圾回收算法它将整个内存区域划分为年轻代和老年代以更高效地管理内存中的对象。这种算法通过将不同生命周期的对象划分到不同的区域来优化垃圾回收的效率和性能。 分代回收时新创建的对象首先会被放入Eden伊甸园区。随着在Eden区中对象数量的增加如果Eden区已满新创建的对象将无法放入此时会触发年轻代的GCMinor GC或Young GC。Minor GC会回收Eden区和From区需要回收的对象并将未被回收的对象放入To区。
随后S0会变成To区S1变成From区。当Eden区再次满时继续往里放入对象会再次触发Minor GC。这次会回收Eden区和S1From中的对象并将Eden和From区中剩余的对象放入S0。
在每次Minor GC中都会为对象记录年龄初始值为0每次GC后加1。如果Minor GC后对象的年龄达到阈值最大15默认值与垃圾回收器有关该对象将被晋升至老年代。
当老年代中空间不足无法放入新的对象时会先尝试Minor GC。如果仍然无法满足空间需求就会触发Full GC。Full GC会对整个堆进行垃圾回收。如果Full GC仍然无法回收老年代中的对象当继续尝试放入对象时就会抛出Out Of Memory异常。 案例 分代回收时创建出来的对象首先会被放入Eden伊甸园区。 当Eden区满时Minor GC或Young GC会被触发。Minor GC会回收Eden区和From区中的对象并将未被回收的对象放入To区。 S0会变成To区S1变成From区未被回收的对象放在From区。当Eden区再次满时Minor GC会被触发回收Eden区和S1(from)中的对象并将剩余对象放入S0区。每次Minor GC会记录对象的年龄。 Minor GC后对象的年龄达到阈值最大15默认值和垃圾回收器有关对象就会被晋升至老年代。 当老年代空间不足Minor GC后仍然无法放入新对象时会触发Full GC对整个堆进行垃圾回收。如果Full GC无法回收老年代的对象当继续放入新对象时会抛出Out Of Memory异常。 在JDK 8中可以使用-XX:UseSerialGC参数来启用分代回收的垃圾回收器并在运行程序时使用Arthas工具来查看分代之后的内存情况。通过Arthas的memory命令可以显示出三个区域的内存情况包括年轻代、老年代和元空间。
调整内存区域的大小
参数名参数含义-Xms设置堆的最小和初始大小必须是1024倍数且大于1MB-Xmx设置最大堆的大小必须是1024倍数且大于2MB-Xmn新生代的大小-XX:SurvivorRatio 伊甸园区和幸存区的比例默认为8 案例新生代1g内存伊甸园区800MBS0和 S1各100MB -XX:PrintGCDetails verbose:gc打印GC日志 案例JDK 8中 public static void main(String[] args) throws IOException {ListObject list new ArrayList();int count 0;while (true){System.in.read();System.out.println(count);list.add(new byte[1024 * 1024 * 1]);}} 调整内存区域的大小 -XX:UseSerialGC -Xms60m -Xmn20m -Xmx60m -XX:SurvivorRatio3 -XX:PrintGCDetails 通过Arthas的memory命令查看三个区域的内存情况 eden_space伊甸园区survivor_space幸存区tenured_gen老年代 通过合理地调整内存区域的大小和配置参数可以更好地平衡垃圾回收的效率和内存使用效率。分代垃圾回收算法的应用广泛是一种有效的垃圾回收策略适用于各种应用场景。 总结 JVM是Java程序的运行环境负责字节码解释、内存管理、安全保障、多线程支持、性能监控和跨平台运行。本文主要介绍了垃圾回收算法评价标准、标记清除算法、复制算法、标记整理算法、分代垃圾回收算法等内容希望对大家有所帮助。