JVM调优-解决native heap持续增长

问题的提出,分析,请参考JNI——小心,内存怪兽出没

(简单的说起来,就是java进程占用了4G内存,但是折腾来折腾去,整个JVM的堆才100M上下,其余的内存凭空消失?刨根问底之后,原来是native heap占用了内存)

看完上面的问题,再来看解决方案:

 

 

 

目前看来,通过调整 JVM 参数来加大 GC 触发的频率是比较现实的一种方式。下面是一些分析过程:

 

一.       判断 Memonry 内存所属的区


通过 jconsole 可以看到 gc 信息,其中新生代的 scavenge 回收比较频繁,如果 Memonry 在这个区应该不存在长期得不到 gc 的情况

由此推测 Memory 应该是在 Tenured/old ,而这个区的内存回收次数恰好非常少。 当然参数优化的目标,就是加大 old 区的 gc 频率。

 

二.       观察 JVM 的堆参数配置

1. 默认配置下,堆的分配起始值为 126M ,最大 1.8G  


 

2. 观察 gc 前后 java 整个堆 的使用情况, gc 前大概占 130M, 远未达到默认设置下的内存容量


 

3. 进一步查看 old 区的内存 ,发现在 gc 前稳定在 90M

而默认参数初始分配 85M ,最大 1.3G ,显然很难触发到 GC


 

三.       解决问题

1. 首要的问题就是控制 JVM 对整个 heap 的大小分配:

 -Xmx300M    指定 jvm 的最大 heap 大小 ,

          -Xms40M   指定 jvm 的最小 heap 大小 ,

 

2. 在减小了整个堆的前提下,优化 NewRatio 这个参数 ( 指定 jvmOld Generation heap sizeNew Generation 的比例 )

            将默认的 NewRatio=2 更改为更符合业务实际内存使用比例的  -XX:NewRatio=1 

           减小了 old 区的比例,更容易触发 gc

 

         3. 另外一个猜测的可行方案:(有待验证)

启用 jvm 中的 gc 参数 -XX:MaxGCPauseMillis=<nnn>

这个参数的大概含义就是,让每次 gc 的时间不超过参数 nnn 。那么 nn 减少的时候,必然会增加到 gc 的次数,来换取每次 gc 的速度。

通过下图的数据可以求出,每次 old 区的 gc 平均耗时 34.7ms 那么可以   -XX:MaxGCPauseMillis=28 ,也许会增加到 gc 频率。


 

 

上述 4 个标红参数已经添加 ,观察几天得到的结论是,比较好的解决了这个问题。

====================================================================

分割线:下面是调优后的观察:

 

可以看到整个内存呈波动结构,Java的堆从20M--》60M就触发一次old区的gc。

下面看看GC的情况: MarkSweep是old区的gc策略,大概2个小时会触发一次,每次耗时

3194/112=28.5178ms,不会对应用产生明显的停摆,并且也验证了MaxGCPauseMillis参数的作用


 

 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值