继续浏览精彩内容
慕课网APP
程序员的梦工厂
打开
继续
感谢您的支持,我会继续努力的
赞赏金额会直接到老师账户
将二维码发送给自己后长按识别
微信支付
支付宝支付

JVM调参

牛魔王的故事
关注TA
已关注
手记 196
粉丝 111
获赞 628

今天看了下之前做的一个异步处理任务的服务,发现占用内存量比较大,达到2G,但我检查了代码,基本没有static对象。但这个服务有个特点,就是每次执行一个任务的时候,会从数据库中捞大量的数据做处理,因此我怀疑是因为有比较多的临时对象产生,但程序没有来的及释放。为了验证这个,我用了jinfo查看和临时设置启动参数,jmap查看内存占用情况和主动触发FGC,jstat查看gc情况,top查看整个程序占用的内存量。

用jmap查看,发现内存占用并没有那么高(free值很大),但capacity比较大。用top查看,整个程序也占用了接近2G,那既然free那么多,为啥程序还占用那么高的内存?是不是因为还没有gc导致?

因此我用jmap做了一次主动gc:/opt/jdk/bin/jmap -histo:live PID,看了top,还是一样大小,只是jmap出来的free值更高了(特别是老年代,新生代的used变成了0),说明gc是有起到作用的。但是,为啥top没有变化??

后来查了jmap出来的参数,MaxHeapFreeRatio参数的意思是,当空闲内存数超出这个值时,会回收内存直到最小内存。而我的程序里面,默认这个值是100,也就是说要所有内存都未使用才会释放(都100%未使用了还需要释放吗?没鸟用了)。为了验证,我用jinfo临时设置了参数:/opt/jdk/bin/jinfo -flag MaxHeapFreeRatio=70 PID,主动触发gc,发现top内存降到了1G。问题解决了。

网上有人遇到top出来的res结果和jmap查出来的结果不一致,具体原因我也没搞懂,但是,只要出发了gc,而且内存做了回收,结果应该跟top出来的结果是一致的。

但jinfo只是临时设置,为了程序每次启动都生效,必须在启动脚本中设置。这个是在gradle中。我的服务有个build.gradle文件,在里面加几个参数:

defaultJvmOpts = ["-XX:MaxHeapFreeRatio=70", "-XX:MaxTenuringThreshold=3", "-XX:MaxNewSize=1073741824"]
MaxTenuringThreshold代表对象的被回收存活次数,
MaxNewSize代表新生代内存大小。

执行build后自动生成启动脚本,搞定!

相关链接:

原文出处:https://www.cnblogs.com/mixerzhan/p/9556415.html

打开App,阅读手记
1人推荐
发表评论
随时随地看视频慕课网APP