起因

线上有Tomcat升级到7.0.52版,然后有应用的JVM FullGC变频繁,在高峰期socket连接数,Cpu使用率都暴增。

思路

思路是Tomcat本身的代码应该是没有问题的,有问题的可能是应用代码升级,或者环境改变了,总之Tomcat的优先级排在最后。

先把应用的heap dump下来分析下:

jmap -dump:format=b,file=path pid

用IBM的Heap Analyser分析,发现dubbo rpc调用的RpcInvocation对象和taglibs的SimpleForEachIterator对象占用了很大部分内存。

正常来说,这两种类型的对象都应该可以很快被回收掉,怎么会占用了那么大的内存空间?是不是有别的对象引用了它们,导致不能释放?

再仔细分析,发现RpcInvocation对象都是root refer的,也就是根对象,正常来说根对象应该可以很快就被回收掉的,为什么在内存中会有那么多对象?

再查看应用的JVM参数:

-Xms2g -Xmx2g -Xmn256m -XX:SurvivorRatio=8 -XX:ParallelGCThreads=8 -XX:PermSize=512m -XX:MaxPermSize=512m -Xss256k -XX:-DisableExplicitGC -XX:+UseCompressedOops -XX:+UseConcMarkSweepGC -XX:+CMSParallelRemarkEnabled

复制

首先发现应用的新生代,即-Xmn256m 设置得太小了。对照上面RpcInvocation对象占用了226M,SimpleForEachIterator占用了267M内存。

显然在新生代里,没办法放下那么多的对象,这些对象必然是被放到老生代(old space)里去了。

既然RpcInvocation对象和SimpleForEachIterator对象应该都是可以很快被回收了,那么思路变成,触发一下线上的FullGC,看下对象有没有被回收。

在触发之前,先用jmap -histo pid统计下对象的数量: 34: 136762 4376384 com.alibaba.dubbo.rpc.RpcInvocation 129: 16345 392280 org.apache.taglibs.standard.tag.common.core.ForEachSupport$SimpleForEachIterator 用 jmap -histo:live <pid> 触发Full GC之后: 294: 625 20000 com.alibaba.dubbo.rpc.RpcInvocation 495: 292 7008 org.apache.taglibs.standard.tag.common.core.ForEachSupport$SimpleForEachIterator 果然数量大大的减少了。

所以结论比较明显了,新生代(Young generation)的空间太小,导致有一些本应该可以很快就被回收的对象被放到了老生代(Old generation)里,导致老生代上涨很快,频繁Full GC。

于是想办法增加新生代的大小,把JVM参数改为:

 -Xms2g -Xmx2g -XX:ParallelGCThreads=8 -XX:PermSize=256m -XX:MaxPermSize=512m -Xss256k -XX:-DisableExplicitGC -XX:+UseCompressedOops -XX:+UseConcMarkSweepGC -XX:+CMSParallelRemarkEnabled 

复制

因为观察到PermSize实际上只用了不到200M,没有必要设置为512M,浪费内存,所以改为 -XX:PermSize=256m -XX:MaxPermSize=512m 。

另外,把新生代最大限制-Xmn256m 去掉。因为默认的NewRatio = 2,即除了PermSize,新生代大约占内存的1/3,即约(2048 - 256) /3 = 597M。和原来相比增大了一倍不止。

修改上线之后,观察发现Old Space增长缓慢,FullGC次数大大减少,时间在50ms下,Yong GC都在10ms下,达到了想要的效果。

简单的GC过程分析

首先来看一张GC的模型图,很形象:

简单来说,对于GC,我们了解到这些信息就足够了。

大部分新对象在Eden Space上分配,当Eden Space满了,则要用到Survivor Space来回收。YGC的算法是很快的。

多次YGC之后,还存活的对象就会被移到Old Generation(old space)上,当Old Generation满了的时候,就会FGC,FGC有通常比较慢。

Permanent Space只要你在开始时分配了足够大的空间,那它可以不用管。

我们可以得出一些结论:

  • 合理减少对象进入老生代;
  • Old Space可能会一直增长,有时没有办法避免不让对象进入Old Space,当然也有一些程序是从来都不执行FGC的;
  • 是不是尽全力防止对象进入老生代?显然不是,有些对象如果长久存在在新生代里,显然加重了YGC的负担,多次YGC之后仍然存活的对象显然应该放到Old Space里。

理想的GC/内存使用情况

总结下来,可以发现,理想的GC情况应该是这样的:

Old Space增长缓慢,FullGC次数少,FullGC的时间短(大部情况应该要在1秒内)。

总结:

尽量少加上一些默认参数。这点我很赞同RednaxelaFX的看法,配置了默认参数除了让后面调优的人蛋疼之外,没有太多的帮助。

GC调优就是一个取舍权衡的过程,有得必有失,最好可以在多个不同的实例里,配置不同的参数,然后进行比较。

有很多命令行工具或者图形工具可以使用,好的工具事半功倍。

参考:

http://www.alphaworks.ibm.com/tech/heapanalyzer‎ IBM Heap Analyser

http://hllvm.group.iteye.com/group/topic/27945 JVM调优的"标准参数"的各种陷阱

JVM GC调优--增大Eden Space提高性能相关推荐

  1. java eden space_JVM GC调优一则–增大Eden Space提高性能

    缘起 线上有Tomcat升级到7.0.52版,然后有应用的JVM FullGC变频繁,在高峰期socket连接数,Cpu使用率都暴增. 思路 思路是Tomcat本身的代码应该是没有问题的,有问题的可能 ...

  2. 一文看尽 JVM GC 调优

    一个著名的学习方法论 向橡皮鸭求助 学会提问,提问也是一门艺术 提问前,先投入自己的时间做好功课 发生了什么事情 问题的基本情况 你投入的研究和发现 能正确提出你的问题,你的问题差不多已经解决一半 深 ...

  3. JVM GC调优参数说明

    GC调优参数 -vmargs 说明后面是VM的参数 -Xmx 最大堆大小(堆内存) -Xms 初始堆大小(堆内存) -XX:pARallelGcThreads=20 配置并行收集器的线程数 -XX:+ ...

  4. JVM GC调优总结 -Xms -Xmx -Xmn -Xss

    堆大小设置 JVM 中最大堆大小有三方面限制:相关操作系统的数据模型(32-bt还是64-bit)限制:系统的可用虚拟内存限制:系统的可用物理内存限制.32位系统下,一般限制在1.5G~2G:64为操 ...

  5. JVM 内存管理、自带性能监测调优工具 (jstack、jstat)及 JVM GC 调优

    0. 内存查看 获取可用内存大小: public static long getAvaliableMemory() {Runtime runtime = Runtime.getRuntime();re ...

  6. Java常量什么时候被回收,JVM GC调优(2)-GC算法判定对象可以被回收(部分摘自深入理解Java虚拟机) - Java 技术驿站-Java 技术驿站...

    这次我们介绍JVM中的GC算法 引用计数法 可达性分析法 首先我们提出四个问题 哪里的内存需要回收? 什么时候回收? 如何回收? Java与C++之间有一堵由内存动态分配和垃圾收集技术所围成的&quo ...

  7. 一张PDF了解JDK10 GC调优秘籍-附PDF下载

    文章目录 简介 Java参数类型 Large Pages JIT调优 总结 简介 今天我们讲讲JDK10中的JVM GC调优参数,JDK10中JVM的参数总共有1957个,其中正式的参数有658个. ...

  8. 一张PDF了解JDK9 GC调优秘籍-附PDF下载

    文章目录 简介 Oracle中的文档 JDK9中JVM参数的变化 废弃的JVM选项 不推荐(Deprecated)的JVM选项 被删除的JVM参数 JDK9的新特性Application Class ...

  9. 深入JVM系列(二)之GC机制、收集器与GC调优

    一.回顾JVM内存分配 需要了解更多内存模式与内存分配的,请看 深入JVM系列(一)之内存模型与内存分配 1.1.内存分配: 1.对象优先在EDEN分配 2.大对象直接进入老年代  3.长期存活的对象 ...

最新文章

  1. 德州仪器Q2净利7.79亿美元 营收32.7亿美元
  2. php中的全局变量$_REQUEST
  3. linux awk语法格式,Awk是什么?一文带运维小白快速掌握Linux Awk用法
  4. 28篇标志性论文见证「自然语言处理NLP」2019-2020年度亮点进展
  5. will_paginate 用作查询分页的注意事项
  6. undefined reference to 'pthread_create'问题解决
  7. Python | 除法
  8. [渝粤教育] 广东-国家-开放大学 21秋期末考试招投标与合同管理10217k2 (2)
  9. 3-1:常见任务和主要工具之软件包管理
  10. windows IOCP模型
  11. 设计模式之美:Strategy(策略) -未经作者同意的转载
  12. java顺序存储_顺序存储-数据结构-java实现
  13. 验证集准确率上不去_Python机器学习之“模型验证”
  14. 小小知识点(十一)——MATLAB中fftshift的作用
  15. 毕业设计 基于STM32停车管理系统 - 物联网
  16. pandas 列计算log不用math.log而是np.log
  17. 单片微机原理与接口技术——8051汇编指令系统与编程基础(2)数据传送指令
  18. k近邻算法与kd树的创建和搜索
  19. iota golang
  20. SMETA验厂辅导,Sedex运营实例和强迫劳工指南额外的关于强迫劳工的指南是可用的

热门文章

  1. win10xp化折腾指南
  2. 2022起重机械指挥考试模拟100题及答案
  3. 一文搞懂EMAS Serverless小程序开发|电子书免费下载
  4. Win10 基于Docker使用tensorflow serving部署模型
  5. 10余年软件开发与系统架构经验,一起聊聊软件开发技术、系统架构技术、以及程序员最真实可行的职场打怪技能,代码之外的生存软技能。
  6. flowable+springboot的使用
  7. web安全性测试用例(输入、输出、SQL注入、跨站请求伪造(CSRF)、跨站脚本攻击(XSS))实实在在的干货
  8. thinkpad x12018换固态_终极之后是否还有究极?ThinkPad X1 Carbon 2018评测
  9. 三分钟搞定dbeaver企业版
  10. 《算法和数据结构》算法零基础五十题讲解