当前位置: 首页 > article >正文

【JVM调优】JVM高频参数和最优实践

JVM高频参数

  • 一、常用参数配置
    • 1. 堆内存设置
      • 方式1(Java8及之前)
      • 方式2(Java9及之后)
    • 2. 新生代和老年代设置
    • 3. 垃圾收集器选择
    • 4. 调试和日志
    • 5. Metaspace设置
    • 6. 其他重要参数
  • 二、参数设置最佳实践
  • 三、GC日志
    • 参数设置
    • 日志解析
      • MinorGC
      • FullGC
    • 日志分析工具

一、常用参数配置

1. 堆内存设置

方式1(Java8及之前)

  • -Xms:设置初始堆大小。
  • -Xmx:设置最大堆大小。

为什么会存在两个堆大小的参数呢?
这里涉及到一个资源利用的问题。一般而言服务的访问量都是存在起伏的,为了最大化利用系统资源,加入初始大小设置(初始堆大小小于最大堆大小),在低谷期分配一个较小的堆空间的话不会浪费系统内存资源,而在之后访问量上升的时候,JVM再动态扩容,直到扩至最大堆限制;
Xms和Xmx设置不同有好处也有坏处:

  • 好处是设计初衷,合理利用系统资源
  • 坏处是服务启动初期可能会由于堆内存不够用而频繁GC、影响性能
    一般情况下建议两个设置相同即可

方式2(Java9及之后)

直接用Xms和Xmx的方式设置堆大小的方式是有缺陷的,比如云端集群化的服务,动态调整服务资源的时候,需要同时手动调整两个参数,Java9引入了新的参数,堆大小不必明确设定一个值,设定为一个系统内存的比例即可,这样机器或者容器内存调整的时候堆内存大小也会跟随动态调整;

  • -XX:+UseContainerSupport:设置JVM检测所处容器(而不是整个操作系统)的内存大小和处理器数量
  • -XX:InitialRAMPercentage=70.0:设置初始堆大小占容器内存比例。
  • -XX:MaxRAMPercentage=70.0:设置最大堆大小占容器内存比例。

2. 新生代和老年代设置

  • -XX:NewRatio=:设置新生代与老年代的比例。
    • 默认值为2,也就是说新生代和老年代默认比例是1:2,但是根据实际服务的情况可以调整为1;
  • -XX:SurvivorRatio=:设置Eden区和Survivor区的比例。
    • 默认值为8,也就是Eden和s1、s2默认比例是8:1:1,这里也可以根据实际情况多分配一些给s区;
  • -XX:MaxTenuringThreshold=:设置对象在新生代的最大存活年龄。
    • 默认15,即经过了15轮minorGC之后就晋升到老年代;
  • -XX:PretenureSizeThreshold:设置直接晋升老年代的对象大小。
    • 默认为0,即默认都走晋升机制

3. 垃圾收集器选择

  • -XX:+UseSerialGC:使用串行垃圾收集器。
  • -XX:+UseParallelGC:使用并行垃圾收集器。
  • -XX:+UseG1GC:使用G1垃圾收集器。
  • -XX:+UseConcMarkSweepGC:使用CMS垃圾收集器。

4. 调试和日志

  • -XX:+PrintGCDetails:打印垃圾回收详细信息。
  • -XX:+PrintGCDateStamps:在GC日志中添加时间戳。
  • -Xloggc::将GC日志输出到指定文件。

5. Metaspace设置

  • -XX:MetaspaceSize=:设置Metaspace的初始大小。
  • -XX:MaxMetaspaceSize=:设置Metaspace的最大大小。

6. 其他重要参数

  • -XX:PretenureSizeThreshold=:设置大对象直接分配到老年代的阈值。
  • -XX:+UseCompressedOops:启用压缩指针以节省内存(适用于64位JVM)。

PretenureSizeThreshold默认是0,也就是JVM默认不会直接晋升对象,而是要走默认晋升机制(15次MinorGC),实际中可以结合自己的服务特殊情况手动设置这个参数调优

二、参数设置最佳实践

JVM的堆(Heap)占用内存过大会引发如下问题:

  • 如果JVM直接运行在Linux系统,可能会导致Java进程被Linux系统的OOM Killer所终止(Kill);
  • 如果JVM运行在Docker容器环境,可能会表现为频繁异常重启。

以下是一套推荐的JVM配置最佳实践:
JVM参数最佳实践

  • 堆内存的指定建议用比例而不是具体值,这个一般设定为系统资源的 70%;
  • GC日志建议带时间戳打印、OOM日志应该dump到文件(毕竟线上环境应该不循序随便上机jstat、jmap)

三、GC日志

参数设置

开启日志打印:-XX:+PrintGC
打印详情:-XX:+PrintGCDetails
收集到指定文件:-Xloggc:filename
开启效果:

[GC (Allocation Failure) [PSYoungGen: 65536K->10730K(76288K)] 65536K->48130K(251392K), 0.0192302 secs] [Times: user=0.19 sys=0.00, real=0.02 secs] 
[GC (Allocation Failure) [PSYoungGen: 76266K->10744K(141824K)] 113666K->96048K(316928K), 0.0315212 secs] [Times: user=0.22 sys=0.00, real=0.03 secs] 
[GC (Allocation Failure) [PSYoungGen: 141816K->10744K(141824K)] 227120K->203431K(335872K), 0.0629411 secs] [Times: user=0.63 sys=0.09, real=0.06 secs] 
[Full GC (Ergonomics) [PSYoungGen: 10744K->0K(141824K)] [ParOldGen: 192687K->186800K(419328K)] 203431K->186800K(561152K), [Metaspace: 3310K->3310K(1056768K)], 1.1488717 secs] [Times: user=7.97 sys=0.03, real=1.15 secs] 
[GC (Allocation Failure) [PSYoungGen: 131072K->10752K(196096K)] 317872K->315546K(615424K), 0.0746573 secs] [Times: user=0.66 sys=0.08, real=0.07 secs] 
[Full GC (Ergonomics) [PSYoungGen: 10752K->0K(196096K)] [ParOldGen: 304794K->279194K(649216K)] 315546K->279194K(845312K), [Metaspace: 3310K->3310K(1056768K)], 1.3879980 secs] [Times: user=10.31 sys=0.00, real=1.39 secs] 
[GC (Allocation Failure) [PSYoungGen: 185344K->10752K(257024K)] 464538K->464974K(906240K), 0.1053396 secs] [Times: user=0.73 sys=0.03, real=0.11 secs] 
[Full GC (Ergonomics) [PSYoungGen: 10752K->0K(257024K)] [ParOldGen: 454222K->410310K(956416K)] 464974K->410310K(1213440K), [Metaspace: 3310K->3310K(1056768K)], 2.2701650 secs] [Times: user=18.20 sys=0.03, real=2.27 secs] 
[GC (Allocation Failure) [PSYoungGen: 173532K->158944K(441344K)] 583843K->569262K(1397760K), 0.4728423 secs] [Times: user=3.28 sys=0.03, real=0.47 secs] 
[GC (Allocation Failure) [PSYoungGen: 392416K->220661K(454144K)] 802734K->793900K(1410560K), 0.1925215 secs] [Times: user=1.63 sys=0.11, real=0.19 secs] 
[Full GC (Ergonomics) [PSYoungGen: 454133K->39886K(454144K)] [ParOldGen: 755767K->956022K(1720320K)] 1209901K->995909K(2174464K), [Metaspace: 6166K->6166K(1056768K)], 5.1099882 secs] [Times: user=43.84 sys=0.11, real=5.11 secs] 
[GC (Allocation Failure) [PSYoungGen: 273358K->265280K(647680K)] 1229381K->1221310K(2368000K), 0.8109806 secs] [Times: user=6.86 sys=0.08, real=0.81 secs] 
[GC (Allocation Failure) [PSYoungGen: 572480K->366592K(673792K)] 1802303K->1794199K(2394112K), 1.2465647 secs] [Times: user=10.16 sys=0.14, real=1.25 secs] 
[GC (Allocation Failure) [PSYoungGen: 673792K->462848K(860672K)] 2101399K->2094679K(2580992K), 1.5548847 secs] [Times: user=12.59 sys=0.22, real=1.55 secs] 
[Full GC (Ergonomics) [PSYoungGen: 462848K->189566K(860672K)] [ParOldGen: 1631831K->1720296K(2746880K)] 2094679K->1909863K(3607552K), [Metaspace: 8764K->8764K(1056768K)], 11.6830036 secs] [Times: user=97.47 sys=0.01, real=11.68 secs] 
Heap
 PSYoungGen      total 926720K, used 226946K [0x000000076b300000, 0x00000007c0000000, 0x00000007c0000000)
  eden space 463872K, 48% used [0x000000076b300000,0x00000007790a0998,0x0000000787800000)
  from space 462848K, 0% used [0x00000007a3c00000,0x00000007a3c00000,0x00000007c0000000)
  to   space 462848K, 0% used [0x0000000787800000,0x0000000787800000,0x00000007a3c00000)
 ParOldGen       total 2780160K, used 2541791K [0x00000006c1800000, 0x000000076b300000, 0x000000076b300000)
  object space 2780160K, 91% used [0x00000006c1800000,0x000000075ca37cc8,0x000000076b300000)
 Metaspace       used 9298K, capacity 9666K, committed 9984K, reserved 1058816K
  class space    used 1074K, capacity 1162K, committed 1280K, reserved 1048576K

日志解析

这里调出两条来看看具体含义

MinorGC

[GC (Allocation Failure) [PSYoungGen: 65536K->10730K(76288K)] 65536K->48130K(251392K), 0.0192302 secs] [Times: user=0.19 sys=0.00, real=0.02 secs] 
  • GC 类型:[GC (Allocation Failure)]
    • 表示这是一次垃圾回收(GC),因为分配失败(即无法为新的对象分配内存)。
  • 年轻代信息:[PSYoungGen: 65536K->10730K(76288K)]
    • 65536K:年轻代回收前的大小。
    • 10730K:年轻代回收后的大小。
    • (76288K):年轻代的总大小(最大可用内存)。
  • 总堆信息:65536K->48130K(251392K)
    • 65536K:总堆在 GC 前的大小。
    • 48130K:总堆在 GC 后的大小。
    • (251392K):总堆的最大可用内存。
  • GC 耗时:0.0192302 secs
    • 表示这次 GC 操作的持续时间为 0.0192302 秒。
  • 其他信息:[Times: user=0.19 sys=0.00, real=0.02 secs]
    • user=0.19:用户 CPU 时间,表示 GC 操作中消耗的用户态 CPU 时间。
    • sys=0.00:系统 CPU 时间,表示 GC 操作中消耗的内核态 CPU 时间。
    • real=0.02 secs:表示实际的墙钟时间,即从开始到结束的总时间。
  • 总结
    • 这条日志表明,在进行垃圾回收时,由于内存分配失败,年轻代的内存被回收,释放了约 54806K 的空间,GC 的处理过程花费了约 19 毫秒。此时,堆的总内存从 65536K 降低到 48130K。

FullGC

[Full GC (Ergonomics) [PSYoungGen: 454133K->39886K(454144K)] [ParOldGen: 755767K->956022K(1720320K)] 1209901K->995909K(2174464K), [Metaspace: 6166K->6166K(1056768K)], 5.1099882 secs] [Times: user=43.84 sys=0.11, real=5.11 secs] 
  • GC 类型:[Full GC (Ergonomics)]
    • 表示这是一次完整的垃圾回收,原因是根据 JVM 的自动调节机制(Ergonomics)触发的。
  • 年轻代信息:[PSYoungGen: 454133K->39886K(454144K)]
    • 454133K:年轻代回收前的大小。
    • 39886K:年轻代回收后的大小,表示释放了大量内存。
    • (454144K):年轻代的最大可用内存。
  • 老年代信息:[ParOldGen: 755767K->956022K(1720320K)]
    • 755767K:老年代回收前的大小。
    • 956022K:老年代回收后的大小,表明在 Full GC 后,老年代的内存使用量增加了。
    • (1720320K):老年代的最大可用内存。
  • 总堆信息:1209901K->995909K(2174464K)
    • 1209901K:总堆在 GC 前的大小。
    • 995909K:总堆在 GC 后的大小。
    • (2174464K):总堆的最大可用内存。
  • Metaspace 信息:[Metaspace: 6166K->6166K(1056768K)]
    • 表示 Metaspace 的大小没有变化,仍然是 6166K,最大可用内存为 1056768K。
  • GC 耗时:5.1099882 secs
    • 表示这次 Full GC 操作的持续时间为 5.1099882 秒。
  • 其他信息:[Times: user=43.84 sys=0.11, real=5.11 secs]
    • user=43.84:用户 CPU 时间,表示 GC 操作中消耗的用户态 CPU 时间。
    • sys=0.11:系统 CPU 时间,表示 GC 操作中消耗的内核态 CPU 时间。
    • real=5.11 secs:表示实际的墙钟时间,即从开始到结束的总时间。
  • 总结
    • 这条日志显示了一次 Full GC,由于内存压力,年轻代释放了大量空间,但老年代的使用量却大幅增加,表明可能有很多对象被晋升到老年代。整个过程持续了约 5 秒,CPU 使用主要集中在用户态。

日志分析工具

  • GCViewer
  • visual VM

个人感觉后者好用一些:
在这里插入图片描述


http://www.kler.cn/news/337651.html

相关文章:

  • 超好用的数据库连接工具-DBeaver连接ClickHouse后找不到系统表?
  • agent实现:通过prompt方式实现agent自定义使用
  • Vue3小兔鲜——订单页
  • 自动驾驶系列—线控悬架技术:自动驾驶背后的动力学掌控者
  • Redis篇(应用案例 - UV统计)(持续更新迭代)
  • 第三十九章 创建安全对话
  • 如何使用 Apt-Get 和 Apt-Cache 在 Ubuntu 和 Debian 中管理软件包
  • 消防隐患在线举报系统开发+ssm论文源码调试讲解
  • Vue 项目文件大小优化
  • 百元头戴式耳机哪款口碑爆棚+质价比高?2024耳机最强推荐攻略!
  • Vue.js组件开发研究
  • 国庆练习(Day24)
  • [OS] 编译 Linux 内核
  • 鲁班到家上门安装维修系统源码开发之结构功能解析
  • 【数据结构】链表-1
  • 力扣 中等 216组合总和III
  • tcpdump-arm平台移植
  • 油卡回收源码含教程
  • Linux 系统成为隐秘“Perfctl”加密挖矿恶意软件的目标
  • 第五弹:C++ 面向对象编程中的多态及相关概念详解