JVM系列学习(四):JVM的内存分析

JVM的内存结构(JDK1.8)

运行时数据区:官方文档

在这里插入图片描述

  1. 程序计数器PC Register:在这里插入图片描述
  2. 虚拟机栈JVM Stacks:在这里插入图片描述
  3. 堆Heap:在这里插入图片描述
  4. 方法区Method Area:在这里插入图片描述
  5. 常量池Run-Time Constant Pool:在这里插入图片描述
  6. 本地方法栈:Native Method Stacks:在这里插入图片描述
  7. 在这里插入图片描述

非堆区Metaspace

  1. Metaspace=Class,Package,Method,Field,字节码,常量池,符号引用等等
  2. CSS:32位指针的Class,压缩空间(64位指针变为32位指针)
  3. CodeCache:JIT编译后的本地代码,JNI使用的C代码

常用参数

  1. -Xms -Xmx
  2. -XX:NewSize -XX:MaxNewSize
  3. -XX:NewRatio -XX:SurvivorRatio
  4. -XX:MetaspaceSize -XX:MaxMetaspaceSize
  5. -XX:+UserCompressedClassPointers
  6. -XX:CompressedClassSpaceSize
  7. -XX:InitialCodeCacheSize
  8. -XX:ReservedCodeCacheSize

垃圾回收算法

工作原理
  1. 思想:枚举根节点,做可达性分析。这是Java虚拟机采用的判定对象是否存活的算法。通过一系列的称为“GC Roots"的对象作为起始点,从这些结点开始向下搜索,搜索所走过的路径称为饮用链(Reference Chain),当一个对象到GC Roots没有任何引用链相连时,则证明此对象是不可用的。可作为GC Roots的对象包括:虚拟机栈中引用的对象、方法区中类静态属性引用的对象、方法区中常量引用的对象。本地方法栈JNI引用的对象
  2. 根节点:类加载器,Thread,虚拟机栈的本地变量表,static成员,常量引用,本地方法栈的变量等等
标记清除
  1. 算法:算法分为“标记”和“清除”两个阶段:首先标记出所有需要回收的对象,在标记完成后统一回收
  2. 缺点:效率不高。标记和清除两个过程的效率都不高。产生碎片。碎片太多会导致提前GC
复制
  1. 算法

    它将可用内存按容量划分为大小相等的两块,每次只使用其中的一块。当这一块的内存用完了,就将还存活着的对象复制到另外一块上面,然后再把已使用过的内存空间一次清理掉。

  2. 优缺点

    实现简单,运行高效,但是空间利用率低,只有50%空间。

标记整理
  1. 算法

    标记过程仍然与“标记-清除”算法一样,但后续步骤不是直接对可回收对象进行清理,而是让所有存活的对象都向一端移动,然后直接清理掉端边界以外的内存。

  2. 优缺点

    没有了内存碎片,但是整理内存比较耗时

分带垃圾回收:JVM采用的方法
  1. Young区用复制算法
  2. Old区标记清除或者标记整理算法
对象分配
  1. 对象优先再Eden区分配
  2. 大对象直接进入老年代:-XX:PretenureSizeThreshold参数来决定
  3. 长期存活对象进入老年代
    • -XX:MaxTenuringThreshold参数来决定存活几次
    • -XX:+PrintTenuringDistribution
    • -XX:TargetSurvivorRatio

垃圾收集器

串行收集器Serial:Serial,Serial Old

  • 主要应用于嵌入式设备,WEB场景不可能使用
  • 开启串行收集器:-XX:+UseSerialGC -XX:+UseSerialOldGC

并行收集器Parallel:Parallel Scavenge,Parallel Old,吞吐量优先

  • 吞吐量优先
  • -XX:+UseParallelGC,-XX:+UseParallelOldGC
  • Server模式下的默认收集器,会根据服务器的配置来启动Client或者Server模式
Parallel Collector:暂停应用程序,启动多个回收器来回收
  • -XX:+UseParallelGC手动开启,Server默认开启
  • -XX:ParallelGCThreads=多少个GC线程
    • CPU>8 N=5/8
    • CPU<8 N=CPU
Parallel Collector Ergonomics 自适应
  • -XX:MaxGCPauseMillis= 优先满足停顿时间的情况下满足吞吐量
  • -XX:GCTimeRatio=
  • -Xmx
动态内存调整参数
  • -XX:YoungGenerationSizeIncrement=
  • -XX:TenuredGenerationSizeIncrement=
  • -XX:AdaptiveSizeDecrementScaleFactor=

并发收集器Concurrent:CMS,G1,停顿时间优先

  • 响应时间优先
  • CMS:-XX:+UseConcMarkSweepGC -XX:+UseParNewGC
  • G1:-XX:+UseG1GC
CMS Collector
  • 并发收集,低停顿,低延迟, 并且是一个老年代收集器
  • CMS垃圾收集过程
    1. CMS initial mark:初始标记Root,STW
    2. CMS concurrent mark:并发标记
    3. CMS-concurrent-preclean:并发预清理
    4. CMS remark:重新标记,STW
    5. CMS concurrent sweep:并发清除
    6. CMS-concurrent-reset:并发重置
  • CMS的缺点
    1. CPU敏感:一个CPU全部都是我的
    2. 浮动垃圾
    3. 空间碎片
  • CMS的相关参数
    • -XX:ConcGCThreads:并发的GC线程数
    • -XX:+UseCMSCompactAtFullConnection:FullGC之后做压缩
    • -XX:CMSFullGCBeforeCompaction:多少次FullGC之后做压缩一次
    • -XX:CMSInitiatingOccupancyFraction:触发FullGC
    • -XX:+UseCMSInitiatingOccupancyOnly:是否动态调整
    • -XX:+CMSScavengeBeforeRemark:FullGC之前先做YGC
    • -XX:+CMSClassUnloadingEnabled:启用回收Perm区
  • iCMS
    • 适用于单核或者双核
G1 Collector
  • 新生代和老生代收集器
  • 在这里插入图片描述
  • Region
  • SATB:Snapshot-At-The-Beginning,它是通过Root Tracing得到的,GC开始时候存活对象的快照
  • RSet:记录了其他Region中的对象引用本Region中对象的关系,属于points-into结构(谁引用了我的对象)
  • YoungGC
    1. 新对象进入Eden区
    2. 存活对象拷贝到Survivor区
    3. 存活时间达到年龄阈值时,对象晋升到Old区
  • MixedGC
    • 不是FullGC一样回收所有的Young和部分Old
    • global concurrent marking全局并发标记
      1. Inital marking phase:标记GC Root,STW
      2. Root region scanning phase:标记存活Region
      3. Concurrent marking phase:标记存活的对象
      4. Remark phase:重新标记,STW
      5. Cleanup phase:部分STW
    • MixedGC时机
      • InitiatingHeapOccupancyPercent: 堆占有率达到这个数值则触发global concurrent marking,默认45%
      • G1HeapWastePercent: 在global concurrent marking结束之后,可以知道区有多少空间要被回收,在每次YGC之后和再次发生Mixed GC之前,会检查垃圾占比是否达到此参数,只有达到了,下次才会发生Mixed GC。
      • G1MixedGCLiveThresholdPercent: Old区的region被回收时候的存活对象对比
      • G1MixedGCCountTarget: 一次global concurrent marking之后,最多执行Mixed GC的次数
      • G1OldCSetRegionThresholdPercent: 一次Mixed GC中能被选入CSet的最多old区的region数量
    • 常用参数
      • -XX:+UseG1GC 开启G1
      • -XX:G1HeapRegionSize=n,region的大小,1-32M,2048个
      • -XX:MaxGCPauseMillis=200 最大停顿时间
      • -XX:G1NewSizePercent,-XX:G1MaxNewSizePercent
      • -XX:G1ReservePercent=10 保留防止to space溢出
      • -XX:ParallelGCThreads=n SWT线程数
      • -XX:ConcGCThreads=n 并发线程数=1/4*并行
    • 最佳实践
      • 年轻代大小:避免使用-Xmn,-XX:NewRatio等显式设置Young区大小,会覆盖暂停时间目标
      • 暂停时间目标:暂停时间不要太严苛,其吞吐量目标是90%的应用程序时间和10%的垃圾回收时间,太严苛会直接影响到吞吐量
    • MixedGC调优
    • 是否需要切换到G1
      • 50%以上的堆被存活对象占用
      • 对象分配和晋升的速度变化非常大
      • 垃圾回收时间特别长,超过了1秒
    • G1 GC的一些关键技术

并行 VS 并发

  • 并行(Parallel):指多条垃圾收集线程并行工作,但此时用户线程仍然处于等待状态。适合科学计算,后台处理等弱交互场景。
  • 并发(Concurrent):指用户线程与垃圾收集线程同时执行(但不一定是并行的,可能会交替执行),垃圾收集线程在执行的时候不会停顿用户程序的运行。适合对响应时间有要求的场景,比如Web

停顿时间VS吞吐量

  • 理想情况:吞吐量最大的时候停顿时间最小,现实情况两者是互斥的
  • 停顿时间:垃圾收集器做垃圾回收中断应用执行的时间 -XX:MaxGCPauseMillis
  • 吞吐量:花在垃圾收集的时间和花在应用时间的占比。 -XX:GCTimeRatio=,垃圾收集时间占:1/1+n

垃圾收集器搭配

在这里插入图片描述

如何选择垃圾收集器

  • 优先调整堆的大小让服务器自己来选择
  • 如果内存小于100M,使用串行收集器
  • 如果是单核,并且没有停顿时间的要求,串行或者JVM自己选
  • 如果允许停顿时间超过1秒,选择并行或者JVM自己选
  • 如果响应时间最重要,并且不能超过1秒,使用并发收集器

GC调优指南

  • JDK1.8下,优先查看官方文档来进行调优指南的学习
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值