`

一次jvm调优

    博客分类:
  • jvm
阅读更多

背景

 

最近在搞一些大数据智能推荐方面的开发工作,为了保证推荐的实时性,没隔10分钟会启动几个worker遍历所有数据 进行检查。

 

程序在预发环境运行一段时间后,偶尔会出现堆内存使用率超过80%的情况(公司监控系统默认堆内存使用率超过80%后,就会报警)。

 

重启后 一段时间内存使用情况是正常的,所以初步怀疑有存在内存泄露。

 

分析问题

 

1、按照内存泄露流程排查:ps -ef|grep java 找到对应java工程的进程号(也可以用top



 

进程号为6206

 

2、然后执行jmap -dump:live,file=/tmp/dump.dat 6206dump文件有点大(几百M),下载下来用 eclipse Memory Analyzer 进行分析(参考

http://blog.csdn.net/xb151652000/article/details/8056792

遗憾的是没有发现异常,难道不是内存泄漏?

 

 

3、查看gc情况:jstat -gcutil 6206

  S0    S1    E      O      M     CCS    YGC     YGCT    FGC    FGCT     GCT  

  0.00   8.33  11.44  76.30  98.24  95.28   9493 1170.869     2    1.964 1172.833

  0.00   8.33  11.47  76.30  98.24  95.28   9493 1170.869     2    1.964 1172.833

  0.00   8.33  11.47  76.30  98.24  95.28   9493 1170.869     2    1.964 1172.833

  0.00   8.33  11.47  76.30  98.24  95.28   9493 1170.869     2    1.964 1172.833

  0.00   8.33  11.48  76.30  98.24  95.28   9493 1170.869     2    1.964 1172.833

 

发现 年老代内存使用率占比,超过70%。初步发现原因所在:YGC 年轻代gc太频繁了(9000多次,从程序启动时算起),FGC fullgc 正常总共就2次。

 

4、再使用命令:jmap -heap 6206看下各个分代内存大小:



 

我晕,s0 s1都自动分配的1M

先看下YGC流程:我们知道每次YGC时,存活下来的对象先从eden复制到s0,年龄为1,第二次YGC还存活从s0复制到s1 年龄为2,第三次YGC s1复制到s0 年龄变为3,当到达最大年龄是再复制到年老代(最大年龄配置-XX:MaxTenuringThreshold=4)。

 

这里s0 s1太小了,根本放不下每次eden中存活下来的对象,形同虚设,所以只能直接迁移到年老代,导致年老代很快打满(YGC时,年轻代内存使用率已经100%)。出现堆内存报警,就不足为奇了。之后就会频繁的出现fullgc(年老代被打满),进入恶性循环。

 

每隔10分钟YGC次数(worker执行时):



 

 

解决问题

 

问题原因:由于我们没有指定堆内存大小,系统默认分配,并根据内存动态调整各个分代内存大小,最终导致s0 s1区分配过小,每次YGC都将存活的对象迁移到年老代。

 

解决办法,jvm 参数手动调整为:

-Xmx2048m -Xms2048m -Xmn1g -Xss512k -XX:SurvivorRatio=8 -XX:+UseParallelGC

-XX:MaxTenuringThreshold=4 -XX:ParallelGCThreads=43

 

-Xmx2048m 最大堆内存2G(之前默认是1G

-Xms2048m 初始堆内存(建议跟-Xmx设置成一样,避免gc后调整)

-Xmn1g  年轻代内存1G

-Xss512k 每个栈大小为512K(设置小点,可以创建更多的线程,设置太小 会栈溢出)

-XX:SurvivorRatio=8  算法(s0+s1)/eden=2:8,即s0=s1=1/10 * 1G=102.4M

-XX:+UseParallelGC 开启并行gc(我们是后端服务,需要大吞吐量)

-XX:MaxTenuringThreshold=4  年轻代对象年龄为4

-XX:ParallelGCThreads  gc线程数,此值最好配置与处理器数目相等。

 

对比

 

重新启动程序,看下内存分配情况(jmap -heap pid):



 

eden = 820M

s0=102M

s1=102M

old=1024M

 

 

gc效果(jstat - gcutil pid):

  S0   S1     E      O      M     CCS    YGC     YGCT    FGC    FGCT     GCT  

 28.51   0.00  22.69   5.31  98.04  95.71      6    1.687     2    1.353    3.040

 28.51   0.00  22.69   5.31  98.04  95.71      6    1.687     2    1.353    3.040

 28.51   0.00  22.69   5.31  98.04  95.71      6    1.687     2    1.353    3.040

 28.51   0.00  22.84   5.31  98.04  95.71      6    1.687     2    1.353    3.040

 28.51   0.00  22.84   5.31  98.04  95.71      6    1.687     2    1.353    3.040

 

通过长时间观察O(年老代) 内存使用率长时间维持在 6%左右,对象在s0 s1区里来回复杂,基本都已经被gc掉了。至此问题解决。

 

优化后,每隔10分钟 YGC次数:



 

 

小结

 

jvm 参数优化不是千篇一律,需要根据具体的业务场景具体调整(我这里是每隔10分钟有一个峰值)。深刻理解每个参数具体含义和用法,反复实践才是关键。

 

开发中也尽量注意代码质量,比如大数据开发中,遍历10万条数据,一定要分配次 一次少量取数据处理,取下一批数的时候让上一批数据成为垃圾。

尽量不要增量的使用全局的MAP List,如果一定要使用,记得清理。

线程池中使用ThreadLocal,也要注意在结束时remove。

 

  • 大小: 10.8 KB
  • 大小: 36.5 KB
  • 大小: 62 KB
  • 大小: 24.5 KB
  • 大小: 20.4 KB
1
0
分享到:
评论
2 楼 moon_walker 2017-05-22  
myDayComing 写道
非常好,非常好的分享

谢谢
1 楼 myDayComing 2017-05-05  
非常好,非常好的分享

相关推荐

    JVM调优文档知识点总结

    JVM是Java Virtual Machine(Java虚拟机)的缩写,JVM是一种用于计算设备的规范,它是一个虚构出来的计算机,是通过在实际的计算机上仿真模拟各种计算机功能来实现的...这就是Java的能够“一次编译,到处运行”的原因。

    resin-jvm 调优

    每次调整时,jvm会对堆进行一次完全的垃圾收集。 使用-XX:MaxPerSize标志来增加永久域搭大小。在WebLogic Server应用程序加载较多类时,经常需要增加永久域的最大值。当jvm加载类时,永久域中的对象急剧增加,从而...

    Java 虚拟机学习笔记:Java 内存区域,垃圾收集,内存分配与回收策略,JVM 调优,文件结构,类加载机制,Java 程序

    它采用了“一次编写,到处运行”的原则,即一次编写的程序可以在不同的操作系统上运行,这得益于Java虚拟机(JVM)的存在。JVM是Java的核心组成部分,它可以将Java代码解释成特定平台上的机器码,从而实现跨平台运行...

    初步理解:jvm运行机制,java程序运行机制,堆栈详解,jvm调优的目的。

    1.一次编写到处运行: 计算机最后执行的是机器码。(jvm)可以将一个代码编译成适用于不同操作系统的机器码,通过不同的jdk(有不同的jvm)实现的。这就是为什么,我们安装对应的jdk不同的jdk版本

    jvm介绍基础,构成和调优

    Java语言的一个非常重要的特点就是与平台的无关性。而使用Java虚拟机是实现这一特点的关键。一般的高级语言如果要在不同的平台上运行,至少需要编译成不同的目标代码...这就是Java的能够“一次编译,到处运行”的原因。

    JVM原理讲解和调优

    JVM是Java Virtual Machine(Java虚拟机)的缩写,JVM是一种用于计算设备的规范,它是一个虚构出来的计算机,是通过在实际的计算机上仿真模拟各种计算机功能来实现的...这就是Java的能够“一次编译,到处运行”的原因。

    JVM的基础和调优【JMM 内存结构 GC OOM 性能调优 ThreadLocal】

    一次的内存泄露似乎不会有大的影响,但是内存泄露堆积的后果就是内存溢出 JMM 决定一个线程对共享变量的写入何时对另一个线程可见,从抽象的角度来看, JMM定义了线程和主内存之间的抽象关系:线程之间的共享变量...

    JVM垃圾回收与调优详解1

    1.JVM 内存分配与回收 2.如何判断对象可以被回收 1. 第一次标记并进行一次筛选 2. 第二次标记 3.垃圾收集算法 1. 效率问题 2. 空间问题(标记

    详细讲解了jvm在java中应用

    主要包含:JVM概述,内存结构讲解,对象实例化,垃圾回收,类的加载,程序编译,代码的优化,性能监控与调优. JVM:全称 Java Virtual Machine,一个虚拟计算机,Java ...即一次编译,处处执行;自动的内存管理,垃圾回收机制.

    java查看sun包源码-monitor:java生产环境内存调优(包括jvm参数类型,JVM的参数类型jinfo&jps(参数和进程查看)j

    -Xcomp:第一次使用就编译成本地代码 -Xmixed:混合模式,JVM 自己决定是否编译成本地代码 示例: java -version(默认是混合模式) Java HotSpot(TM) 64-Bit Server VM (build 25.40-b25, mixed mode) java -Xint -...

    高级java笔试题-StudySpark:学习Spark的一个小项目,以及其中各种调优的笔记

    高级java笔试题 StudySpark spark的一个小项目以及笔记 目录 项目内容 用户访问session分析模块 用户访问session分析业务,session...性能调优方案:普通调优、jvm调优、shuffle调优、算子调优 troubleshooting经验 数

    JVM 实用参数系列 - v1.0.pdf

    JVM 是 Java Virtual Machine(Java 虚拟机)的缩写,Java 通过使用 Java 虚拟机屏蔽了与具体平台相关的 信息,使得 Java 具备了一次编写,多处运行的特性。JVM 一直是 Java 学习中的重点,也是难点。本教程旨在 帮助...

    WebLogic宕机大全总结

    本文主要是本人在实际的生产环境中遇到WebLogic宕机问题,经过自己的经验整理而总结的文档,对从事中间件的人将会是很好的参考。

    hello-beginner:github 最全技术类思维导图

    当然,如果你想一次性下载所有的脑图,扫码下方任意二维码关注后回复 999 即可。 分类下载 Docker学习 密码:yu9m Git基础 密码:s2iq Java并发体系 密码:3ixn JVM和性能调优 密码:dmpg Kafka 密码:pigv Mysql优化 ...

    Java虚拟机

    这本书的内容是帮你全面了解java虚拟机,本书第1版两年内印刷近10次,98%以上的评论全部为5星级的好评,是整个Java图书领域公认的经典著作和超级畅销书,繁体版在台湾也十分受欢迎。第2版在第1版的基础上做了很大的...

    从无到有搭建中小型互联网公司后台服务架构与运维架构

    4、 作为一个技术架构肯定涉及java性能调优,所以之后会根据图示讲解jvm里的一系列东西,帮助大家充分了解jvm 5、 讲解消息中间件redis,以及高可用集群搭建,以及里面的数据类型,分布式以及一致性问题的讲解 6、 ...

    Hadoop权威指南(中文版)2015上传.rar

    重用JVM 跳过坏记录 任务执行环境 第7章 MapReduce的类型与格式 MapReduce的类型 默认的MapReduce作业 输入格式 输入分片与记录 文本输入 二进制输入 多种输入 数据库输入(和输出) 输出格式 文本输出 二进制输出 ...

    Hadoop权威指南 第二版(中文版)

     二次排序  联接  map端联接  reduce端联接  边数据分布  利用JobConf来配置作业  分布式缓存  MapReduce库类 第9章 构建Hadoop集群  集群规范  网络拓扑  集群的构建和安装  安装Java  创建Hadoop用户...

Global site tag (gtag.js) - Google Analytics