前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >JVM技术总结之一——JVM调优

JVM技术总结之一——JVM调优

作者头像
剑影啸清寒
发布2020-07-20 10:19:19
4130
发布2020-07-20 10:19:19
举报
文章被收录于专栏:琦小虾的Binary琦小虾的Binary

一. JVM 调优

1.1 JVM 调优如何使用

笔者首先会使用到的工具:

  • java 自带工具:JVisualVM 用于监控,jstack 查看线程状态,jmap 用于堆 dump;
  • Memory Analyser:载入堆 dump 文件,进行分析。
  • 在项目启动的时候,加入 -XX:+PrintGCDetails 参数,可以观察 GC 的频率。观察 GC 频率可以判断 GC 频率是否正常(主要是针对 Full GC)。如果不正常,就可以观察 GC 日志,并且针对 GC 的频率进行原因的猜测。
  • 如果有堆 Dump 文件,则可以观察内存中占据最大空间的对象是什么,如果有特定的某些对象占据了太大的对象,则需要重新考虑是否有可以优化的空间?(比如 C3P0 连接池资源过大,太多的 HashMap 节点占据过大内存等)

1.2 GC 回收算法

  1. 标记-清除算法:对需要回收的对象进行标记,然后清除;
  2. 复制算法:将内存区域分为两部分 A, B 区域,发生 GC 时,将 B 区域的所有内容复制到 A 区域,然后清除 B 区域所有内容。发生第二次 GC 时反过来。
    • 适用于朝生夕死对象较多的情况下;
    • 在实际使用时 (如 Parallel Scavange 收集器),多数情况下只在两块小区域中进行复制操作,这两块小区域通常是在新生代中。新生代分为三部分:Eden + Survivor * 2 (To Survivor, From Survivor),三者比例通常为 8:1:1。通常如果发生 minor GC 时,将 Eden + Survivor1 的存活的对象全部拷贝到 Survivor2 中,然后将 Eden 和 Survivor1 的全部对象清除。
  3. 标记-整理算法:将需要回收的对象进行标记并清除,然后内存碰撞,所有对象的内存移到一端。
  4. 分代回收算法:垃圾收集器大多都是只针对新生代或者老年代,所以商用的垃圾收集器一般都会分别针对新生代与老年代,用不同的分代回收算法进行垃圾回收。

1.3 GC 回收策略

有几种不同的垃圾收集器,不同收集器各自有各自的收集对象以及收集策略;

1.3.1 Serial

Serial + Serial Old 收集器:两者都是串行收集器;Serial 收集器用于新生代的 Minor GC,单线程的 STW GC;Serial Old 收集器用于旧生代,单线程的 STW Full GC;

1.3.2 ParNew

ParNew 收集器是Serial 收集器的多线程版本,用于新生代的 GC,通常与 CMS 收集器搭配使用。

1.3.3 Parallel Scavenge + Parallel Old

Parallel Scavenge + Parallel Old 收集器,两者都是并行收集器,且都是强调 GC 时间的垃圾收集器。可以通过设置垃圾收集的比率 (程序时间 / (程序时间 + GC 时间)),或者 GC 最大时间,来保障 GC 时间不会过长。但这样也牺牲了新生代空间大小,以及吞吐量大小。

  • Parallel Scavenge: 针对新生代,使用复制算法。
  • Parallel Old: 针对旧生代,使用标记-整理算法。

1.3.4 CMS 收集器

参考地址:《GC之详解CMS收集过程和日志分析》

CMS (Concurrent Mark Sweep) 收集器用于旧生代,它的设计目的是为了减少回收时间。为了实现这一目的,首先 CMS 用了列表数据结构,用来管理回收可利用空间;另外 GC 线程与用户线程并行处理(即 GC 过程中也会同时执行服务逻辑)。CMS 收集器使用标记-清除算法,步骤如下:

  1. 初始标记 (Initial Mark):
    • 第一次 Stop the world,用来标记 GC Roots 直接关联的对象,以及新生代中存活对象的引用对象;
  2. 并发标记 (Concurrent Mark):
    • 标记 GC Roots 链上的所有对象,GC 线程与应用线程并行执行;
    • 该过程不会 Stop the world,但时间最长;
  3. 重新标记 (Final Remark):
    • 第二次 Stop the world,标记在并发标记过程中产生的对象,时间不长;
    • 过程中包含两次并发预清理 (Concurrent Preclean);
  4. 并发清除 (Concurrent Sweep):
    • 对所有被标记的对象进行并行的回收(使用标记-清除算法);
  5. 并发重置线程 (Concurrent Reset):
    • 并发的重置 CMS 算法内部的数据结构,准备下一个 CMS 生命周期的使用;

CMS 收集器虽然使用了标记-清除算法,可能会出现大量的内存碎片,但可以通过设置虚拟机参数,使得在 Full GC 之后执行空间压缩合并,清理内存碎片。

1.3.5 G1 收集器

G1 收集器是一种新式的收集器,对旧生代、新生代没有明确的区分对待,因为它将堆内存划分为若干个 Region,旧生代和新生代与之前的定义不同,物理上不再隔离。标记清除的步骤和 CMS 收集器相似。

1.4 GC 分配内存策略

  1. 给对象分配内存时,首先优先分配到 Eden 区;随着 GC 次数的增加,Eden + Survivor1/2 的内存会用 minor GC 的复制算法将内存转移到 Survivor2/1 中,这样的操作会让对象的 GC 年龄 +1;
  2. 对于比较大的对象 (比如较长的 String 或者数组),可能会直接进入旧生代。在虚拟机参数中可以设置该参数 -XX:PertenureSize,大于该值的对象便直接进入旧生代。
  3. 对于年龄比较大的对象,即经过了多次 minor GC 的对象,会进入旧生代。虚拟机参数 -XX:MaxTenuringThreshold 设置该值,默认值为 1;
  4. 并非所有对象年龄都必须达到 MaxTenuringThreshold 值才会晋升老年代,虚拟机会针对根据对象年龄,以及对象的大小,动态的判定是否可以直接进入老年代。Survivor 空间中相同年龄所有对象的大小之和大于 Survivor 空间的一半,年龄大于或等于该年龄的对象可以直接进入旧生代;
  5. 分配担保策略:在进行 Minor GC 之前,判断旧生代可用空间是否大于新生代中所有对象大小之和;如果是,则这次 Minor GC 是安全的;如果不是,则需要根据虚拟机参数 HandlePromotionFailure 值,判断是否允许担保失败。如果该值为是,判断老年代可用空间是否大于一个经验值,如果大于,则尝试一次 MinorGC,如果小于,则进行 Full GC。

注:GC 机制见《JVM技术总结之二——GC机制》

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2020-07-16 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一. JVM 调优
    • 1.1 JVM 调优如何使用
      • 1.2 GC 回收算法
        • 1.3 GC 回收策略
          • 1.3.1 Serial
          • 1.3.2 ParNew
          • 1.3.3 Parallel Scavenge + Parallel Old
          • 1.3.4 CMS 收集器
          • 1.3.5 G1 收集器
        • 1.4 GC 分配内存策略
        相关产品与服务
        Elasticsearch Service
        腾讯云 Elasticsearch Service(ES)是云端全托管海量数据检索分析服务,拥有高性能自研内核,集成X-Pack。ES 支持通过自治索引、存算分离、集群巡检等特性轻松管理集群,也支持免运维、自动弹性、按需使用的 Serverless 模式。使用 ES 您可以高效构建信息检索、日志分析、运维监控等服务,它独特的向量检索还可助您构建基于语义、图像的AI深度应用。
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档