Java性能调优实战
刘超
金山软件西山居技术经理
立即订阅
7535 人已学习
课程目录
已完结 48 讲
0/4登录后,你可以任选4讲全文学习。
开篇词 (1讲)
开篇词 | 怎样才能做好性能调优?
免费
模块一 · 概述 (2讲)
01 | 如何制定性能调优标准?
02 | 如何制定性能调优策略?
模块二 · Java编程性能调优 (10讲)
03 | 字符串性能优化不容小觑,百M内存轻松存储几十G数据
04 | 慎重使用正则表达式
05 | ArrayList还是LinkedList?使用不当性能差千倍
加餐 | 推荐几款常用的性能测试工具
06 | Stream如何提高遍历集合效率?
07 | 深入浅出HashMap的设计与优化
08 | 网络通信优化之I/O模型:如何解决高并发下I/O瓶颈?
09 | 网络通信优化之序列化:避免使用Java序列化
10 | 网络通信优化之通信协议:如何优化RPC网络通信?
11 | 答疑课堂:深入了解NIO的优化实现原理
模块三 · 多线程性能调优 (10讲)
12 | 多线程之锁优化(上):深入了解Synchronized同步锁的优化方法
13 | 多线程之锁优化(中):深入了解Lock同步锁的优化方法
14 | 多线程之锁优化(下):使用乐观锁优化并行操作
15 | 多线程调优(上):哪些操作导致了上下文切换?
16 | 多线程调优(下):如何优化多线程上下文切换?
17 | 并发容器的使用:识别不同场景下最优容器
18 | 如何设置线程池大小?
19 | 如何用协程来优化多线程业务?
20 | 答疑课堂:模块三热点问题解答
加餐 | 什么是数据的强、弱一致性?
模块四 · JVM性能监测及调优 (6讲)
21 | 磨刀不误砍柴工:欲知JVM调优先了解JVM内存模型
22 | 深入JVM即时编译器JIT,优化Java编译
23 | 如何优化垃圾回收机制?
24 | 如何优化JVM内存分配?
25 | 内存持续上升,我该如何排查问题?
26 | 答疑课堂:模块四热点问题解答
模块五 · 设计模式调优 (6讲)
27 | 单例模式:如何创建单一对象优化系统性能?
28 | 原型模式与享元模式:提升系统性能的利器
29 | 如何使用设计模式优化并发编程?
30 | 生产者消费者模式:电商库存设计优化
31 | 装饰器模式:如何优化电商系统中复杂的商品价格策略?
32 | 答疑课堂:模块五思考题集锦
模块六 · 数据库性能调优 (8讲)
33 | MySQL调优之SQL语句:如何写出高性能SQL语句?
34 | MySQL调优之事务:高并发场景下的数据库事务调优
35 | MySQL调优之索引:索引的失效与优化
36 | 记一次线上SQL死锁事故:如何避免死锁?
37 | 什么时候需要分表分库?
38 | 电商系统表设计优化案例分析
39 | 数据库参数设置优化,失之毫厘差之千里
40 | 答疑课堂:MySQL中InnoDB的知识点串讲
模块七 · 实战演练场 (4讲)
41 | 如何设计更优的分布式锁?
42 | 电商系统的分布式事务调优
43 | 如何使用缓存优化系统性能?
44 | 记一次双十一抢购性能瓶颈调优
结束语 (1讲)
结束语 | 栉风沐雨,砥砺前行!
Java性能调优实战
登录|注册

24 | 如何优化JVM内存分配?

刘超 2019-07-16
你好,我是刘超。
JVM 调优是一个系统而又复杂的过程,但我们知道,在大多数情况下,我们基本不用去调整 JVM 内存分配,因为一些初始化的参数已经可以保证应用服务正常稳定地工作了。
但所有的调优都是有目标性的,JVM 内存分配调优也一样。没有性能问题的时候,我们自然不会随意改变 JVM 内存分配的参数。那有了问题呢?有了什么样的性能问题我们需要对其进行调优呢?又该如何调优呢?这就是我今天要分享的内容。

JVM 内存分配性能问题

谈到 JVM 内存表现出的性能问题时,你可能会想到一些线上的 JVM 内存溢出事故。但这方面的事故往往是应用程序创建对象导致的内存回收对象难,一般属于代码编程问题。
但其实很多时候,在应用服务的特定场景下,JVM 内存分配不合理带来的性能表现并不会像内存溢出问题这么突出。可以说如果你没有深入到各项性能指标中去,是很难发现其中隐藏的性能损耗。
JVM 内存分配不合理最直接的表现就是频繁的 GC,这会导致上下文切换等性能问题,从而降低系统的吞吐量、增加系统的响应时间。因此,如果你在线上环境或性能测试时,发现频繁的 GC,且是正常的对象创建和回收,这个时候就需要考虑调整 JVM 内存分配了,从而减少 GC 所带来的性能开销。
取消
完成
0/1000字
划线
笔记
复制
© 版权归极客邦科技所有,未经许可不得传播售卖。 页面已增加防盗追踪,如有侵权极客邦将依法追究其法律责任。
该试读文章来自付费专栏《Java性能调优实战》,如需阅读全部文章,
请订阅文章所属专栏。
立即订阅
登录 后留言

精选留言(24)

  • bro.
    堆外内存创建有两种方式:1.使用ByteBuffer.allocateDirect()得到一个DirectByteBuffer对象,初始化堆外内存大小,里面会创建Cleaner对象,绑定当前this.DirectByteBuffer的回收,通过put,get传递进去Byte数组,或者序列化对象,Cleaner对象实现一个虚引用(当内存被回收时,会受到一个系统通知)当Full GC的时候,如果DirectByteBuffer标记为垃圾被回收,则Cleaner会收到通知调用clean()方法,回收改堆外内存DirectByteBuffer

    作者回复: 回答很全面,赞!

    2019-07-22
    13
  • QQ怪
    盲目增大堆内存可能会让吞吐量不增反减,堆内存大了,每次gc扫描对象也就越多也越需要花费时间,反而会适得其反

    作者回复: 对的。合理设置堆内存大小,根据实际业务调整,不宜过大,也不宜过小。

    2019-07-16
    5
  • 青梅煮酒
    超哥好,我们经常发现生产环境内存使用超过90%持续3分钟,没有outofmer,
    dump下来堆没有发现问题,这种情况每不确定几小时就会一次,求解答

    作者回复: 你好,某一时间段高峰值的访问可能会有这种情况,JVM会最大可能进行对象的回收,防止内存溢出异常的发生。如果不是内存泄漏,或者瞬时并发量大大超过预期并发量的情况,几乎很少发生内存溢出异常。

    建议结合内存持续占用率以及Full GC发生的频率来分析调优。

    2019-07-16
    1
    2
  • 迎风劲草
    老师,你的这个抢购场景下我理解是不是新生代越大越好,因为对象都是生命周期较短的对象。尽量在新生代中被回收掉。

    作者回复: 也不是越大越好,因为新生代过大,会导致minor gc的停顿时间过长。

    我们知道,如果新生代很快就满了,会以担保的方式将新增的对象直接分配到老年代,这样增加了老年代回收的成本,这个成本跟具体的垃圾收集器相关。所以我们需要适当的调大年轻代,将对象尽量留在年轻代回收。

    如果调整太大,我们知道每次Minor GC分为对象标记和复制两个阶段,并且都是STW的,如果对象过于庞大,有可能标记时间要大于复制时间,这样反而适得其反。

    2019-07-18
    1
  • Levvy
    最大堆内存1593M 还有124M 这俩数字是在哪看的,我怎么找不到

    作者回复: 在jmap -heap pid运行之后,有一个MaxHeapSize,这个就是1953M,还有一个是NewSize以及OldSize,加起来就是初始化的124M大小。

    2019-12-04
  • 赤城
    根据老师的教程,在测试项目中,将年轻代的大小调整为3g,发现的确性能提升了,Mirror GC的次数也大大减少,但是Full GC的次数也明显多了几倍,这个是因为年轻代的空间过大,压缩了老年代的内存大小吗?
    java -jar -Xms4g -Xmx4g -Xmn3g heapTest-0.0.1-SNAPSHOT.jar
    2019-11-13
  • 殷传宁
    吞吐量那个图是怎么查看的?方法能说一下吗?

    作者回复: 使用AB工具运行后会自动打印出这些信息,回顾下加餐篇《加餐 | 推荐几款常用的性能测试工具》

    2019-10-13
  • 没有小名的曲儿
    超哥好,我们线上的的服务器经常会进行图片处理,内存15G,堆内存设置的-Xms与-Xmx都是10G,经常在进行图片处理时,用top查看java进程,占用率高达79.1%。
    等传完之后,观察内存一直都是这么多。jmap也看了,是正常回收的。并且各个代free率很高,但是top查看java进程内存一直占用79.1%。
    是不是因为设置了-Xms为10G,尽管GC了,也不会降低占用整个分配的物理内存呢?

    作者回复: 如果内存一直没有释放,我想跟内存设置比例没有关系,可能是引用没有释放,尝试在传完之后手动释放内存试试

    2019-09-30
  • SDL
    老师 为什么我用这个java -XX查看某个参数都没有相关信息输出的?就只有版本号那些信息呢

    作者回复: java -X可以查看部分JVM参数信息

    2019-09-26
  • 小笨蛋
    请问堆内存的分配有没有一个大概的标准😭既然都提到了不能太大也不能太小

    作者回复: 需要根据自己的项目来具体做配置,如果不清除具体需要的配置大小,使用默认配置就可以了

    2019-09-17
  • godtrue
    课后思考及问题
    1:JVM 内存分配不合理最直接的表现就是频繁的 GC,这会导致上下文切换等性能问题,从而降低系统的吞吐量、增加系统的响应时间。
    频繁的GC,GC线程和应用线程会频繁的切入切出,所以,降低了系统的性能。
    2:老师好,现在有这么一个问题,我们有一个定时任务跑一次大概会有2亿条数据一条数据大概40kb大小,一次大概7.4TB多的数据,分布式任务50台机器需要刷新2个多小时,我们需要持久化,为了提高性能做了异步发送MQ到另外的机器来持久化,不过MQ积压严重,数据跑一次耗时太长,有什么建议的优化思路嘛?拆分消息会加剧业务处理的复杂度,目前我能想到的是加机器加带宽。请老师给个优化的思考?

    作者回复: 优化传输性能,例如使用特定的数据结构序列化与反序列化传输数据(protobuff序列化),并且提高单台服务并行处理能力。

    2019-09-11
  • 风轻扬
    老师,如果允许分配担保机制失败。那即使老年代的空间不足以吃下年轻代的对象。jvm也会冒险进行minor gc的。gc之后,如果老年代还是吃不下对象,这个时候才会Full GC。那关闭这个分配担保机制,感觉好一点啊,反正有Full GC兜底呢😃

    作者回复: 打开分配担保机制,是为了避免Full GC过于频繁。

    2019-09-10
  • 疯狂咸鱼
    ab压测是什么工具的

    作者回复: 是一种简单的压力测试工具,可以网上查询下资料

    2019-09-03
  • 涛哥迷妹
    你好,请问G1调优能不能也讲讲。主要应该注意些什么和cms这种调优的差异

    作者回复: 嗯,在后面的答疑课堂中讲到了,有问题欢迎提出

    2019-08-29
  • 高鑫
    大大,有个问题请教。如果survivor区不能容纳eden区的活跃对象,那么这些对象会直接晋升到oldgen么?能否详述一下对象晋升的流程🥰
    2019-07-25
  • 晓杰
    可以通过directBuffer创建堆外内存,full gc可以对堆外内存进行回收
    2019-07-17
  • 晓杰
    full gc会对堆外内存进行回收
    2019-07-17
  • 歪曲丶
    Unsafe DirectByteBuffer都可以直接开辟堆外内存 啥时候回收 可以在full gc的时候回收 难的是堆外的阈值设定 监控堆外内存 jmx好像取不到堆外的大小了吧 之前看到R大在1.7的时候粗略的算下的 有种可能是老年代引用堆外的引用 但是old gc或者full gc迟迟不gc 那堆外就有可能oom
    2019-07-17
  • 我又不乱来
    超哥,有两个疑问。
    当第一次创建对象的时候 eden 空间不足会进行一次minor gc把存活的对象放到from s区。如果这个时候from s放不下。会发生一次担保进入老年代吗?
    当一次创建对象的时候eden空间不足进入from s区。当第二次创建对象的时候eden空间又不足了,这个时候会把,eden和第一次存在from s 区的对象进行gc 存活的放在 to s区,to s区空间不足,进行担保放入老年代?这样的理解对吗。

    作者回复: 对的,细节把握的很好!

    前提是老年代有容量这些对象的空间,才会进行分配担保。如果老年代剩余空间小于每次minor gc晋升到老年代的平均值,则会发起一次Full GC。

    2019-07-16
  • LW
    老师的压测结果图形化是用什么工具做的?

    作者回复: Excel

    2019-07-16
收起评论
24
返回
顶部