JVM垃圾收集基础

JVM垃圾收集基础

基础知识
这里介绍的只是JVM垃圾收集的一些基础知识入门,后面会有文章展开讨论细节。



为什么需要垃圾回收

    我们现在的计算机中,内存是十分珍贵的,一般家用计算机也就8G左右,随着CPU的快速迭代,处理速度也越来越快,可以同时处理的任务也越来越多。但是内存需要存放程序代码,但是这个空间显然是有限的。即使有虚拟内存也是不够的。
    所以现在的大部分的编程语言都会涉及的垃圾回收。但是每种语言的回收策略也是不同的。

C++:手工处理垃圾
缺点:也容易引起了一些问题,比如忘记回收造成内存泄露,多次回收造成的非法访问,而 且程序员开发效率低,很容易写出bug。
优点:执行效率高。

java:垃圾回收
缺点:执行效率低
优点:开发效率高,不同意引起上述问题。


垃圾收集基础

1.1 如何去判断是一个垃圾?

  • 引用计数法: 会造成循环引用
  • 根可达算法 :GC Roots(线程栈变量 静态变量 常量池 JNI指针)
    在这里插入图片描述

在这里插入图片描述

1.2垃圾收集算法

  • 标记清除 mark-sweep:1.实现简单,效率高 2.容易产生内存碎片 3.适合垃圾对象少的情况
  • 复制算法 copy:1.适合存活对象较少的情况 2.没有内存碎片 3.空间浪费 4.需要调整对象引用地址
  • 标记压缩 mark-compact:1.不会产生内存碎片 2.扫描2次,需要移动对象,效率低

在这里插入图片描述
在这里插入图片描述

1.3 JVM内存分代模型

新生代 (young)+ 老年代 (old) + 永久代(1.8以下)/元数据区(1.8开始)

  • 新生代 : 复制算法(大部分对象存活时间较短),会触发MinorGC/YGC,设置大小:-Xmn
  • 老年代: 标记清除(大部分对象存活时间较长),会触发MarjorGC/FullGC,设置大小:-Xms Xmx

G1:逻辑分代,物理不分代。
ZGC:没有使用这个内存分代模型
大部分GC都是这个内存分代模型

在这里插入图片描述

1.4 对象分配

  • 栈上分配 1.小对象 2.无逃逸 3.标量替换
  • 线程本地分配TALB 1.占用eden,默认1% 2.多线程避免竞争申请eden区域
  • 老年代 1.大对象直接分配老年代
  • 年轻代

默认开启:逃逸 标量替换 TALB
开启逃逸分析: (-XX:+DoEscapeAnalysis)
开启标量替换: (-XX:+EliminateAllocations)
TALB : -XX: +UseTLAB

1.5 对象何时进入老年代

  • 超过 XX:MaxTenuringThreshold(控制对象经过GC多少次仍然存活后晋升到老年代的最大阈值),默认15
  • 动态年龄 1.s1 -> s2超过50% ,年龄最大直接进入Old
  • 分配担保:YGCsurvivor区空间不足,空间担保直接进入老年代。

1.6 常见的垃圾收集器

  • Serial:单线程的,到达安全点(safe point)进行STW(用户线程全部停止),单CPU使用
  • Parallel Scavenge:多线程的,也会造成STW,年轻代,吞吐量优先
  • Parallel Old: 多线程的,也会造成STW,老年代
  • ParNew: 多线程的,增强的Parallel Scavenge和配合CMS使用,响应时间优先,年轻代
  • CMS:开启了并发回收的过程,但是问题较多。

垃圾收集器和内存大小关系?
Serial:几十兆
PS:上百兆-几个G
CMS:20G
G1:上百G
ZGC: 4T-16T

CMS

并发:工作线程和垃圾回收线程并发执行

过程:

  • 1.初始标记(寻找gcroots)
  • 2.并发标记(寻找垃圾对象) 占用大部分时间
  • 3.重新标记(寻找并发阶段的产生的垃圾)
  • 4.并发清理(会产生浮动垃圾)

问题:

  • 浮动垃圾
  • 碎片内存
  • 并发回收造成的内存不足

cms问题:并发回收造成的内存不足
CMS垃圾回收报错(Concurrent Model Failure) 并发失败。
启动后备预案:冻结用户线程的执行,临时启用Serial Old收集器来重新进行老年代的垃圾收集。(这样的话时间就会变得很长)
解决:在JDK1.5之前老年带使用了68%空间后就会激活CMS收集。如果实际应用中可以适当调整参数-XX:CMSInitiatingOccu-pancyFraction 的值来提高CMS的触发百分比,降低内存回收频率获得更好的性能。
到了JDK6 CMS收集器的启动阀值就已经默认提升到92%。

三色标记:

1.颜色含义

  • 白色:未标记
  • 灰色:自身标记,成员变量未标记
  • 黑色:自身和成员变量标记

2.漏标
在这里插入图片描述

解决办法:
1.增量更新,关注引用增加 (CMS)
2.关注引用删除(B-D),把引用推到GC的堆栈 (G1使用RSet避免扫描整个堆)

G1

特点:

  • 可预测的停顿时间–暂停时间特别短–200ms
  • 较好的吞吐量(没有ps垃圾收集器好)
  • 逻辑分代( Eden Survivor Old Humongous)
  • Regin分区 2^n(最大32M)
  • 压缩空间不会延长GC停顿时间

概念

  • CSst(Collection Set) 一组可以被回收的分区集合
  • RSet(RememberedSet)记录每个Region中对象到本Region引用
  • 新生代老年代比例动态调整 5%-60%

GC触发

  • YGC
    Eden空间不足触发
    MixedGC:堆空间占用总空间45%,触发垃圾回收(相当于CMS)

  • FGC
    Old空间不足触发
    java10以前是串行回收

优化:

  • G1产生FGC如何优化?
    1 增加内存 2.提高CPU性能,回收性能提升 3.降低MixedGC触发阈值,让MixedGC提早触发(45%)

多租户JVM

  • 每租户单独空间
  • session based GC

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值