java进阶-优化GC垃圾回收机制

1.1什么是垃圾回收机制?

在程序运行期间,用来回收堆内产生了很多对象却不在使用的"垃圾"。让堆内的空闲空间更大

1.2垃圾回收机制执行过程中需要识别哪些对象是不使用的、在合适的时机去清除、用合适的算法去清除。

识别不再使用对象的方法

1、引用计数法:给每个对象一个计数器,有引用就+1,引用失效就-1,当计数器为0的时候,就是表示不再使用的对象;该方法优点是简单,缺点是不是满足以上条件就是代表废对象,比如对象a引用对象b,对象b引用对象a,两个计数都为1,但是两者都不被任何一个对象引用,却无法收回

2、可达性分析法:通过一系列GC-ROOT(根对象)为起点,线下开始搜索,走过的路径叫引用链,如果一个GC-ROOT没有任何引用链相连,则代表是废对象,可以回收

GC-ROOTS包含:

方法区中静态属性引用的对象、常量引用的对象、本地方法栈引用的对象、活跃的线程、虚拟机栈中引用的对象。

在合适的时机清除垃圾

GC不是一直在工作,它是有自己的触发条件的,主要是两类:一类是创建的对象充满了新生代堆频率快,速度快;第二类是老年代被充满时,频率低,速度慢,会导致STW。

用合适的算法去清除

1、标记-清除算法:先标记所有要回收的对象,再统一清除所有被标记的对象;优点是算法简单,缺点是标记和清除过程效率不高;在清除的时候会产生大量碎片

2、复制算法:将内存容量划分为大小相等的两块,每次只使用其中一块。当这一块用完了,就将还活着的对象复制到另外一块,然后把已经使用过的空间内存一次性清理掉;优点是实现简单运行效率高,没有内存碎片;缺点是可用内存缩小为原来的一半,浪费有点多,用于新生代多一点。

3、标记-整理算法:标记过程与标记-清除算法一样,但不直接清理,而是让所有存活的对象都向一端移去,然后直接清除掉端边界以外的内存。优点是没有内存碎片,缺点是移动对象成本相对较高。

4、分代收集法(JVM实际采用):该算法是把内存分为几个区域,每个区域使用最适合的算法。

1.3垃圾回收机制的代价(STW)

定义:当进行垃圾回收的时候,除了垃圾线程之外,其他的工作线程都被暂停掉。

影响:STW的长短直接影响到程序的响应速度

优化STW

方式1:分代收集-缩小STW的范围:JVM把内存分为新生代和老年代,避免每次GC都扫描整个堆,使扫描新生代的频率高,减少STW。

方式2:并行收集-加速STW的过程:在STW干活期间,启动多个GC线程工作,减少STW时间时间,代价是需要多核cpu,线程切换有开销,使用于追求高吞吐量的后台计算任务,可接受短暂的STW.

方式3:并发标记-让STW几乎消失:GC线程和应用程序线程尽量同时进行。

方式4:增量收集--化整为零:不再一次要求一次性回收整个新生代或老年代,G1把整个堆划分为诸多小块。它每一次只选一部分垃圾最多的小块进行回收;代价:回收的吞吐量可能会有点下降,但停顿时间变得可控且可预测。

方式5:无停顿收集器

通过指针染色、读屏障、染色指针等先进技术,使得绝大多数垃圾回收阶段都能于应用线程并发进行,甚至连对象移动都可以并发进行;代价实现复杂,对cpu有一定额外开销。

1.4在实际中如何减少STW

1、合理设置堆大小:太小容易触发GC,太大容易使STW时间增加;原则需要找到平衡点,根据业务特性调整。一般建议不超过32G(G1)。

2、调整新生代和老年代比例

如果业务中临时对象非常多,适合增大新生代,让这些对象在Min GC中快速消亡,避免过早进去老年代引发full GC,

3、设置大对象阈值

如果程序经常创建大对象(大数组),可以设置这个参数,让大对象直接进入老年代,避免Edent区和Surivivor区之间复制产生大量内存拷贝开销

4、选择合适的GC收集器

响应速度优先(低延迟):web应用、游戏服务器、交易系统->选择(G1)JDK9默认,CMS(jdk常用,或ZGC。

吞吐量优先(高计算):后台数据分析、科学计算-->选择ParallelGC(JDK8默认)

5、使用CMS时候预防碎片化

6、代码层面优化

避免在频繁调用的方法中创建大量临时对象,减少GC压力;合理使用对象池,服用对象,避免频繁创建和销毁;注意显式调用System.gc:会触发FullGC

相关推荐
安卓程序员_谢伟光2 小时前
如何用MAT(Eclipse Memory Analyzer)
java·ide·eclipse
喵喵蒻葉睦2 小时前
力扣 hot100 和为K的子数组 哈希&前缀和
java·数据结构·算法·leetcode·前缀和·哈希算法
G探险者2 小时前
DDD开发模式说明
java·运维·数据库
Amour恋空2 小时前
SpringBoot使用SpringAi完成简单智能助手
java·spring boot·后端
lang201509282 小时前
18 Byte Buddy 进阶:揭秘方法委托中的“歧义解析”机制
java·byte buddy
SimonKing2 小时前
Spring Boot 动态多数据源:核心思路与关键考量
java·后端·程序员
REDcker2 小时前
glibc、libstdc++ 与 libc++ 区别与联系
开发语言·c++
2401_844221322 小时前
内存对齐与缓存友好设计
开发语言·c++·算法
好家伙VCC2 小时前
**NumPy中的高效数值计算:从基础到进阶的实战指南**在现代数据科学与机器学习领域
java·python·机器学习·numpy