目前在一家电信公司就职报表开发工程师,2010年开始从事运维方面的工作,期间从事过业务维护工程师、自动化运维工程师,2016年转为报表开发工程师。有耐心,抗压力、爱折腾,喜欢研究自动化工具。
分类: 系统运维
2019-04-09 17:00:48
查看JVM内存使用和垃圾回收情况
JVM内存泄漏是性能故障的主要原因之一,由于JVM内存使用情况极易获取,我们将内存作为第一排查对象,在讲如何查看内存使用情况之前,先普及一下JVM内存结构和垃圾回收的相关知识:
JVM内存结构:线程独享内存、线程共享内存
线程共享内存:新生代(young Gen)、老年代(old Gen)、永久代(perm Gen)一般不会发生内存泄漏
Java常量刚刚实例的对象在Edenspace 堆区即s0 s1
java内存泄漏一般发生在线程共享区的老年代(old Gen)
JVM垃圾回收(GC)作用:清理共享内存,将已失去应用的对象从内存中清楚。
JVM垃圾回收有两种方式:
1、Young GC :回收速度快,通常在毫秒级,触发条件Eden space满了。
2、Full GC : 回收速度非常慢,测试1.4G的old Gen进行一次回收需要20-40秒,触发条件是old Gen满了。
如图:E是Edenspace满了,发生了Young GC
如图:O是old Gen满了,发生一次Full GC
分析JVM内存泄漏导致服务不可用的原因:当出现内存泄漏时,一些对象会占用大量的JVM内存,且长时间无法被JVM回收掉,这些长时间无法被回收的对象通常会在old Gen中;由于old Gen中存在大量的无法被回收的对象,每次full Gc只能释放极少的old Gen空间,回收出的这极少部分old Gen空间很快又被占满,这就会导致JVM频繁的进行Full GC,前文提到过Full GC的速度很慢,而JVM在做Full GC的时候stop-the-world,即在Gc是终止一切工作,所以我们可以假设在内存泄漏发生时,JVM被迫60秒一次Full GC,一次Full GC需要30s,这就代表jvm只有二分之一时间正常工作,此时的性能肯定非常慢,而随着泄漏的对象不断的增多,Full GC加快,最后JVM没有工作时间,一直在Full GC,此时服务彻底不可用。
实例:
如果jstat命令输出的信息表示JVM正在频繁的Full Gc,那么基本可以肯定性能故障的原因是内存泄漏,此时需要通过进一步的手段定位内存泄漏点,内存dump文件分析通过jmap -dump:format=b,file=(filename) (pid)命令导出dump文件,一般内存dump文件比较大肉眼是不可读的,需要通过工具进行分析,注意:内存文件输出时,JAVA的虚拟机jvm是不工作的。