深入了解JVM调优:解锁Java应用程序性能的秘诀-CSDN博客

我是廖志伟一名Java开发工程师、Java领域优质创作者、CSDN博客专家、51CTO专家博主、阿里云专家博主、清华大学出版社签约作者、产品软文创造者、技术文章评审老师、问卷调查设计师、个人社区创始人、开源项目贡献者。跑过十五公里、徒步爬过衡山、有过三个月减肥20斤的经历、是个喜欢躺平的狠人。

拥有多年一线研发和团队管理经验研究过主流框架的底层源码(Spring、SpringBoot、Spring MVC、SpringCould、Mybatis、Dubbo、Zookeeper)消息中间件底层架构原理(RabbitMQ、RockerMQ、Kafka)、Redis缓存、MySQL关系型数据库、 ElasticSearch全文搜索、MongoDB非关系型数据库、Apache ShardingSphere分库分表读写分离、设计模式、领域驱动DDD、Kubernetes容器编排等。有从0到1的高并发项目经验利用弹性伸缩、负载均衡、报警任务、自启动脚本最高压测过200台机器有着丰富的项目调优经验。

经过多年在CSDN创作上千篇文章的经验积累我已经拥有了不错的写作技巧。同时我还与清华大学出版社签下了四本书籍的合约并将陆续在明年出版。这些书籍包括了基础篇、进阶篇、架构篇的《Java项目实战—深入理解大型互联网企业通用技术》以及《解密程序员的思维密码–沟通、演讲、思考的实践》。具体出版计划会根据实际情况进行调整希望各位读者朋友能够多多支持

以梦为马不负韶华

希望各位读者大大多多支持用心写文章的博主现在时代变了信息爆炸酒香也怕巷子深博主真的需要大家的帮助才能在这片海洋中继续发光发热所以赶紧动动你的小手点波关注❤️点波赞点波收藏⭐甚至点波评论✍️都是对博主最好的支持和鼓励

在这个美好的时刻本人不再啰嗦废话现在毫不拖延地进入文章所要讨论的主题。接下来我将为大家呈现正文内容。

CSDN
深入了解JVM调优解锁Java应用程序性能的秘诀

JVM调优

JVM调优情况十分复杂各种情况都可能导致垃圾回收不能够达到预想的效果。对于场景问题可以从如下几个大方向进行设计

增大Eden 空间大小

大访问压力下MGC 频繁一些是正常的只要MGC 延迟不导致停顿时间过长或者引发FGC 那可以适当的增大Eden 空间大小降低频繁程度同时要保证空间增大对垃圾回收产生的停顿时间增长是可以接受的。

如果MinorGC 频繁且容易引发 Full GC

需要从如下几个角度进行分析。

S1 区大小 < MGC 存活的对象大小对象的年龄才1岁

每次MGC存活的对象的大小是否能够全部移动到 S1区如果S1 区大小 < MGC 存活的对象大小这批对象会直接进入老年代。注意 了这批对象的年龄才1岁很有可能再多等1次MGC 就能被回收了可是却进入了老年代只能等到Full GC 进行回收很可怕。这种情况下应该在系统压测的情况下实时监控MGC存活的对象大小并合理调整eden和s 区的大小以及比例。

相同年龄的对象所占总空间大小>s1区空间大小的一半

还有一种情况会导致对象在未达到15岁之前直接进入老年代就是S1区的对象相同年龄的对象所占总空间大小>s1区空间大小的一半所以为了应对这种情况对于S区的大小的调整就要考虑尽量保证峰值状态下S1区的对象所占空间能够在MGC的过程中相同对象年龄所占空间不大于S1区空间的一半 因此对于S1空间大小的调整也是十分重要的。

解决方案
调整年龄阈值

可以通过设置 JVM 参数"-XX:MaxTenuringThreshold"来调整年龄阈值。该参数指定对象晋升老年代的最大年龄通常默认值为15岁。可以逐渐增加该值以减少老年代中相同年龄对象的数量。

请注意调整年龄阈值需要根据具体应用程序的情况来确定。如果将年龄阈值设置得太高可能会导致年轻代中的对象数量过多从而增加Young GC的频率进而影响系统性能。

增加S区的大小

如果S区足够大那么S1区所占的比例就会更小。这样可以降低相同年龄段对象的总空间大小从而使其不大于S1区的一半。

改变对象分配的位置
  • 设置对象的大小阈值。通过调整对象分配的大小阈值可以让 JVM 将较大的对象分配到老年代中减少新生代中对象数量从而减少垃圾回收的频率。可以通过 -XX:PretenureSizeThreshold 参数来设置对象的大小阈值。
  • 调节新生代大小。通过调整新生代的大小可以增加对象在新生代中的寿命从而让更多的对象进入老年代减少在新生代中对象的数量。可以通过调整 -Xmn 参数来设置新生代的大小。
  • 调节垃圾回收器参数。不同的垃圾回收器有不同的参数可以根据具体的情况调节垃圾回收器的参数以达到更好的效果。比如使用 G1 垃圾回收器可以通过调节 -XX:G1HeapRegionSize 参数来控制 region 的大小从而控制对象在不同 region 中的分配情况。

大对象创建频繁

由于大对象创建频繁导致Full GC 频繁。对于大对象JVM专门有参数进行控制-XX PretenureSizeThreshold。超过这个参数值的对象会直接进入老年代只能等到full GC 进行回收所以在系统压测过程中要重点监测大对象的产生。如果能够优化对象大小则进行代码层面的优化优化如根据业务需求看是否可以将该大对象设置为单例模式下的对象或者该大对象是否可以进行拆分使用或者如果大对象确定使用完成后将该对象赋值为null方便垃圾回收。

代码层面无法优化

如果代码层面无法优化则需要考虑

调高-XX PretenureSizeThreshold参数的大小

调高-XX PretenureSizeThreshold参数的大小使对象有机会在eden区创建有机会经历MGC以被回收。但是这个参数的调整要结合MGC过程中Eden区的大小是否能够承载包括S1区的大小承载问题。

大对象必须进入老年代

这是最不希望发生的情况 如果必须要进入老年代也要尽量保证该对象确实是长时间使用的对象放入老年代的总对象创建量不会造成老年代的内存空间迅速长满发生Full GC在这种情况下可以通过定时脚本在业务系统不繁忙情况下主动触发full gc。

MGC 与 FGC 停顿时间长

MGC 与 FGC 停顿时间长导致影响用户体验。其实对于停顿时间长的问题无非就两种情况

gc 真实回收过程时间长

gc 真实回收过程时间长即real time时间长。这种时间长大部分是因为内存过大导致从标记到清理的过程中需要对很大的空间进行操作导致停顿时间长。这种情况要考虑减少堆内存大 小包括新生代和老年代比如之前使用16G的堆内存可以考虑将16G 内存拆分为4个4G的内存区域可以单台机器部署JVM逻辑集群也可以为了降低GC回收时间进行4节点的分布式部署这里的分布式部署是为了降低 GC垃圾回收时间。

gc真实回收时间 real time 并不长

gc真实回收时间 real time 并不长但是user time(用户态执行时间) 和 sys time核心态执行时间时间长导致从客户角度来看停顿时间过长。这种情况要考虑线程是否及时达到了安全点通过-XX+PrintSafepointStatistics和-XX PrintSafepointStatisticsCount=1去查看安全点日志如果有长时间未达到安全点的线程再通过参数-XX +SafepointTimeout和-XXSafepointTimeoutDelay=2000两个参数来找到大于2000ms到达安全点的线程这里 的2000ms可以根据情况自己设置然后对代码进行针对的调整。除了安全点问题也有可能是操作系统本身负载比较高导致处理速度过慢线程达到安全点时间长因此需要同时检测操作系统自身的运行情况。

内存泄漏导致的MGC和FGC频繁最终引发oom

纯代码级别导致的MGC和FGC频繁。如果是这种情况那就只能对代码进行大范围的调整这种情况就非常多了而且会很糟糕。如大循环体中的new 对象未使用合理容器进行对象托管导致对象创建频繁不合理的数据结构使用等等。 总之JVM的调优无非就一个目的在系统可接受的情况下达到一个合理的MGC和FGC的频率以及可接受的回收时间。

JVM调优步骤

1. 收集数据

使用命令或GUI工具收集JVM内存和处理器使用信息并生成堆转储快照。

2. 分析数据

使用工具分析收集到的数据计算GC吞吐量和新生代大小等分析堆中对象的分布情况查看是否有内存泄漏等问题。

3. 制定优化方案

根据分析的数据确定具体的优化方案比如调整内存大小、垃圾回收机制、优化代码等。尝试调整GC算法、分配大对象空间、增加GC并行度等进行GC调优尝试减少对象的创建、复用对象等进行内存调优。

4. 验证优化效果

使用性能测试工具进行压力测试验证优化效果是否符合预期。

5. 持续监控

持续监控应用程序及时发现并解决新问题进行JVM调优。

CSDN

如果您需要转载或者搬运这篇文章的话非常欢迎您私信我哦~

希望各位读者大大多多支持用心写文章的博主现在时代变了信息爆炸酒香也怕巷子深博主真的需要大家的帮助才能在这片海洋中继续发光发热所以赶紧动动你的小手点波关注❤️点波赞点波收藏⭐甚至点波评论✍️都是对博主最好的支持和鼓励

博主的人生感悟和目标

探寻内心世界博主分享人生感悟与未来目标

  • 程序开发这条路不能停停下来容易被淘汰掉吃不了自律的苦就要受平庸的罪持续的能力才能带来持续的自信。我本身是一个很普通程序员放在人堆里除了与生俱来的盛世美颜就剩180的大高个了就是我这样的一个人默默写博文也有好多年了。
  • 有句老话说的好牛逼之前都是傻逼式的坚持希望自己可以通过大量的作品、时间的积累、个人魅力、运气、时机可以打造属于自己的技术影响力。
  • 内心起伏不定我时而激动时而沉思。我希望自己能成为一个综合性人才具备技术、业务和管理方面的精湛技能。我想成为产品架构路线的总设计师团队的指挥者技术团队的中流砥柱企业战略和资本规划的实战专家。
  • 这个目标的实现需要不懈的努力和持续的成长但我必须努力追求。因为我知道只有成为这样的人才我才能在职业生涯中不断前进并为企业的发展带来真正的价值。在这个不断变化的时代我必须随时准备好迎接挑战不断学习和探索新的领域才能不断地向前推进。我坚信只要我不断努力我一定会达到自己的目标。
阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6
标签: Java