《Android学习笔记总结+最新移动架构视频+大厂安卓面试真题+项目实战源码讲义》
完整开源地址:https://docs.qq.com/doc/DSkNLaERkbnFoS0ZF
正常删除是指移除未引用的对象,留下引用的对象和指向空闲空间的指针。
3.压缩删除(Deletion with Compacting)
要进一步提高性能,除了删除未引用的对象外,还可以压缩剩余的引用对象。
通过将引用的对象移动到一起,这使得新的内存分配更加容易和快速。
二、全自动回收管理
当正在进行垃圾收集时,如果你的应用程序在该时间段内没有响应时,其实我们的期望是,GC应该花费最少的时间来回收它; 当然, 如果花费很多时间,则证明你的应用GC设置是有问题滴。
我们来看看下面的JVM内存模型,它分为不同的部分。JVM堆内存在物理上分为两部分 - Young Generation(新生代)和Old Generation(老年代)。
1.首先,将所有新的对象都分配给伊Eden space(伊甸园)。两个Survivor Space(幸存者区)都是空的。
2.当Eden space(伊甸园)填满时,会触发一个小的垃圾收集。
3.引用的对象被移动到第一个幸存者空间。清除Eden space(伊甸园)时,将删除未引用的对象。
4.下次要GC回收时,Eden space(伊甸园)空间也会发生同样的事情。删除未引用的对象,并将引用的对象移动到幸存者空间。但是,在这种情况下,它们被移动到第二个幸存者空间(S1)。
5.在较小的GC之后,当老化的对象达到一定的年龄阈值(在该示例中为8)时,它们从新生代晋升到老年代。
最终,将对老一代进行主要的GC回收,清理和压缩该空间。
三、如何在Java中调整垃圾收集的优化参数呢?
垃圾收集是指当JVM不再需要对象时,需要将它回收,释放内存。它包括查找不再使用的对象,释放与这些对象关联的内存,并偶尔压缩堆以防止内存碎片。
垃圾收集器使用一个或多个线程来执行回收工作。一般来说,为了完成跟踪对象引用及在内存中移动对象的工作,它需要确保应用程序线程当前没有使用这些对象,如果应用程序线程正在使用对象,GC回收时会导致对象的内存位置发生变化,可能发生不可预测的事情。这就是垃圾收集器在执行某些任务时必须暂停所有应用程序线程的原因。这些暂停有时被称为Stop-The-World暂停(吊炸天,全世界都被停止,哈哈)。
3.1调整堆大小
垃圾收集调优的第一步是调整堆的大小。这是因为如果堆太小,则会发生太多的GC回收回收内存次数,这会降低整体应用程序吞吐量。如果堆太大,那么GC回收次数会更少,但GC需要很长的时间,那么你的系统响应时间指标会受到影响。并行收集器特别容易受到堆大小的影响,因此如果你需要大的堆并且暂停时间较短,那么你应该尝试使用G1GC收集器。
备注:自从Java 9和Shenandoah垃圾收集器被视为还处于“实验性”阶段,不推荐使用并发标记扫描(CMS)收集器。但如果你正在运行在线交互式应用程序,那么系统会默认选择G1GC收集器,如果你正在运行脱机批处理应用程序,那么并行收集器应该是你的首选,这是我给大家的建议。
堆的大小由两个值控制:使用ms标志指定的初始值和使用mx标志指定的最大值。
-Xms1g -Xmx8g
堆的初始大小和最大大小,可以由JVM根据工作负载自动调整堆大小。如果JVM遇到内存压力并且观察到GC执行次数过多,它会不断增加堆,直到内存压力消失为止,或直到堆达到其最大值为止。如果内存压力很低,JVM还可以通过缩小堆大小来决定减少暂停时间。这个过程称为自适应大小调整,它不仅可以调整堆的整体大小,还可以调整年轻代和老代的大小和比例。
当然,如果你想调整GC行为和大小,我建议你可以选择关闭自适应大小调整。这可以节省JVM,这是计算堆大小所需的一小段时间。你可以通过将标志设置UseAdaptiveSizePolicy为false 来执行此操作。
-XX:-UseAdaptiveSizePolicy
此外,将初始堆大小设置为与最大堆大小相同的值,或将初始新生代大小设置为与最大新生代大小相同的值,这样操作可以有效地关闭自适应大小调整。
一般来说堆大小的最大设置准则就是最大堆大小不应超过计算机上的物理内存量。如果你运行多个JVM,则最大堆大小的总和不应超过计算机的物理内存。
3.2调整GC性能
在G1GC中,调整参数MaxGCPauseMillis执行以下所有优化,以尝试实现指定的暂停时间目标:
· 调整堆的大小
· 更快开始后台处理,
· 调整要提升为旧一代的对象的期限阈值,
· 调整混合GC循环期间处理的旧区域数。
指定的暂停时间目标:
· 调整堆的大小
· 更快开始后台处理,
· 调整要提升为旧一代的对象的期限阈值,
· 调整混合GC循环期间处理的旧区域数。