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

JVM性能调优技巧

目录

设置堆内存大小及GC输出日志

GC日志文件分析

CPU过高问题定位

堆内存溢出问题定位

栈内存溢出

项目运行越来越慢原因分析


        本文是基于JDK8设置的JVM参数。

  • 设置堆内存大小及GC输出日志

        示例说明:设置堆内存大小50M,打印GC日期,时间,GC产生的原因以及GC日志目录

-Xms50m -Xmx50m -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+PrintGCTimeStamps -XX:+PrintGCCause -Xloggc:D:\tmp\gclog.log

        JVM参数设置可以通过在线工具:https://opts.console.heapdump.cn/ 生成,很多参数可以满足生产要求。

  • GC日志文件分析

        分析上述导出的gclog.log文件,文件内容包含几类信息,如下:

        1、JDK信息

        2、内存信息

        3、项目对应jvm参数信息

        4、年轻代垃圾回收信息

        其中:

        2025-08-12T10:24:40.728+0800:表示垃圾回收时间,由-XX:+PrintGCDateStamps 生成

        1.080:相对时间,应用启动多久触发回收,由-XX:+PrintGCTimeStamps 生成

        GC (Allocation Failure) :GC原因,由-XX:+PrintGCCause 生成

        PSYoungGen:不同的垃圾回收展示不同,本文用的垃圾回收是-XX:+UseParallelGC ,所以展示PSYoungGen

        12800K:回收前年轻代使用的大小

        2040K:回收后年轻代使用的大小

        14848K:年轻代的总大小

        12800K->2417K(49152K):分别表示年轻代堆内存回收前、回收后,堆内存总大小(年轻代+老年代)

        0.0043385 secs:本次垃圾回收耗时

        5、老年代垃圾回收信息

        其中:

        2025-08-12T10:24:41.880+0800:表示垃圾回收时间,由-XX:+PrintGCDateStamps 生成

        2.232:相对时间,应用启动多久触发回收,由-XX:+PrintGCTimeStamps 生成

        Full GC (Metadata GC Threshold):GC原因,由-XX:+PrintGCCause 生成

        ParOldGen:不同的垃圾回收展示不同,本文用的垃圾回收是-XX:+UseParallelGC ,所以展示ParOldGen

        10309K:回收前老年代使用的大小

        7295K:回收后老年代使用的大小

        34304K:老年代的总大小

        11158K->7295K(46592K):分别表示老年代堆内存回收前、回收后,堆内存总大小(年轻代+老年代)

        0.0372030 secs:本次垃圾回收耗时

        Times: user=0.09 sys=0.02, real=0.04 secs:分别表示用户、系统、实际时间

        在实际项目中,人工分析gc日志比较繁琐,借助工具分析相对容易,可以考虑通过GCeasy (https://gceasy.io/)或GCviewer分析,下方示例以GCviewer分析上述gc日志。

        GC调优核心的是使得应用卡顿时间越短,即Stop the World越来越短,应用的吞吐量越大(吞吐量:应用程序所花费的时间和系统总运行时间的比值,系统总运行时间=应用程序耗时+GC耗时,应用的吞吐量一般不低于95%)。

  • CPU过高问题定位

        定位步骤如下:

        1、使用top命令查询到占用cpu最大的进程 top

        2、查看进程内部线程运行信息 top -Hp 进程号,找到cpu占用最大的线程号

        3、将线程号转换为16进制数 printf %x 线程号

        4、jstack出jvm信息到文件中  jstack 1605 >cupHigh.log

        5、到文件中定位问题,查看文件中包含16进制线程号的信息

        下方示例:找到文件中包含646及向后50行的记录,进而定位到问题代码位置。

  • 堆内存溢出问题定位

        步骤图下:

        1、启动项目时增加内存溢出报错后,输出dump文件

java -Xms5m -Xmx5m -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=./heapdump.hprof -jar jvm-0.0.1-SNAPSHOT.jar 

        2、下载dump文件到本地,用jvisualvm工具分析dump文件

        从示例图看出,JvmApplication的第20行heapOOM()方法抛出oom的错误

  • 栈内存溢出

        步骤如下:

        1、通过设置-Xss大小控制每个线程的栈空间大小,如:-Xss100k

        2、通过日志文件中的stackOverflowError排查异常错误,定位到程序代码位置

        3、栈内存溢出很多时候是由于递归引起的,需要合理设置递归的结束条件

  • 项目运行越来越慢原因分析

        总结如下原因(实际情况不限于如下原因):

        1、GC耗时长,导致应用吞吐量降低

        可以通过分析GC日志定位问题并解决

        2、JVM中代码缓存(code cache)设置不合理

        CodeCache 是有限的,默认大小受 JVM 参数控制(如 -Xx:ReservedCodeCacheSize),一旦使用率过高,可能没有足够的空间来存储新生成的 JIT 编译代码。当 CodeCache 空间不足时,方法不会被编译,只能以解释模式运行,这会显著降低性能。

        3、项目依赖资源越来越慢,如数据库、网络等

        需要查看数据库、网络的状态分析原因及解决

        4、项目线程数量过多,导致线程之间争抢激烈

        通过jvisualVM工具分析Threads ,或将Thread dump出来,用fastthread(https://fastthread.io/)分析dump文件定位原因

        5、服务器问题,如操作系统问题或者被其他应用进程争抢资源

http://www.dtcms.com/a/328286.html

相关文章:

  • Java集合学习之forEach()遍历方法的底层原理
  • 数据科学与计算:爬虫和数据分析案例笔记
  • 01数据结构-Kruskal算法
  • 破译真实感:渲染参数进阶指南——告别塑料感,唤醒材质生命力
  • 01. maven的下载与配置
  • ubuntu24下keychorn键盘连接不了的改建页面的问题修复
  • “生成式UI革命”:Tambo AI如何让你的应用“开口说话、动手搭界面” | 全面深剖、案例实践与未来展望
  • Seed-VC:零样本语音转换与扩散transformer
  • 08--深入解析C++ list:高效操作与实现原理
  • 从爬虫新手到DrissionPage实践者的技术旅程
  • 【IP查询】使用IP66(ip66.net)验证IP地址定位的准确率
  • 小智智能交互算法通过国家备案,视觉大模型引领AI应用新浪潮
  • 机器学习之TF-IDF文本关键词提取
  • 终端安全检测与防御技术
  • 数据结构:中缀到后缀的转换(Infix to Postfix Conversion)
  • 【速通版!语义通信基础与前沿学习计划】
  • C++中类之间的关系详解
  • AR巡检:三大核心技术保障数据准确性
  • Langchain入门:构建一个PDF摄取和问答系统
  • 51 单片机分层架构的模块依赖关系图
  • 解决ROS编译顺序不对,需要内部依赖,因此要多次编译的问题
  • Python初学者笔记第二十二期 -- (JSON数据解析)
  • MySQL 数据库表操作与查询实战案例
  • 双十一美妆数据分析:洞察消费趋势与行业秘密
  • 机械臂的智能升维:当传统机械臂遇见Deepoc具身智能大模型从自动化工具到具身智能体的范式革命
  • Element用法---Loading 加载
  • C++的异常的使用和规范
  • 【盘古100Pro+开发板实验例程】FPGA学习 | 均值滤波 | 图像实验指导手册
  • 【代码随想录day 18】 力扣 501.二叉搜索树中的众数
  • 免费播客翻译与转录:用中文收听全球播客