一.引言

1.编写目的

为了方便大家以后发现进程假死的时候能够正常的分析并且第一时间保留现场快照。

2.编写背景

最近服务器发现tomcat的应用会偶尔出现无法访问的情况。经过一段时间的观察最近又发现有台tomcat的应用出现了无法访问情况。简单描述下该台tomcat当时具体的表现:客户端请求没有响应,查看服务器端tomcat的进程是存活的,查看业务日志的时候发现日志停止没有任何最新的访问日志。连tomcat下面的catalina.log也没有任何访问记录,基本断定该台tomcat已不能提供服务。

二.分析步骤

根据前面我描述的假死现象,我最先想到的是网络是否出现了问题,是不是有什么丢包严重的情况,于是我开始从请求的数据流程开始分析,由于我们业务的架构采用的是nginx+tomcat的集群配置,一个请求上来的流向可以用下图来简单的描述一下:

1.检查nginx的网络情况

更改nginx的配置,让该台nginx请求只转到本机器的出现问题的tomcat应用上面,在access.log里看是否有网络请求,结果可以查看到当前所有的网络请求,也就是说可以排除是网络的问题。

2.检查tomcat 的网络情况

分析业务配置的tomcat访问日志xxxx.log上是否有日志访问记录,经过查询该台tomcat应用日志完全没有任何访问记录,由于我们的部署是本机的nginx转到本机的tomcat应用,所以可以排除不是网络问题。到此基本可以断定网络没有问题,tomcat 本身出现了假死的情况。在tomcat的日志里有报过OutOfMemoryError的异常,所以可以肯定tomcat假死的原因是OOM

三.分析JVM内存溢出

1.为什么会发生内存泄漏

在我们学习Java的时候就知道它最为方便的地方就是我们不需要管理内存的分配和释放,一切由JVM自己来进行处理,当Java对象不再被应用时,等到堆内存不够用时JVM会进行GC处理,清除这些对象占用的堆内存空间,但是如果对象一直被应用,那么JVM是无法对其进行GC处理的,那么我们创建新的对象时,JVM就没有办法从堆中获取足够的内存分配给此对象,这时就会导致OOM。我们出现OOM原因,一般都是因为我们不断的往容器里存放对象,然而容器没有相应的大小限制或清除机制,这样就容易导致OOM。

2.快速定位问题

当我们的应用服务器占用了过多内存的时候,我们怎么样才能快速的定位问题呢?要想快速定位问题,首先我们必需获取服务器JVM某时刻的内存快照。Jdk里面提供了很多相应的命令比如:jstack,jstat,jmap,jps等等. 在出现问题后我们应该快速保留现场。

1).jstack

可以观察到jvm中当前所有线程的运行情况和线程当前状态.

sudo jstack -F 进程ID

输出内容如下:

从上面的图我们可以看到tomcat进程里面没有死锁的情况,而且每个线程都处理等待的状态。这个时候我们可以telnet命令连上tomcat的端口查看tomcat进程是否有任务回应。这时发现tomcat没有任何回应可以证明tomcat应用已没有响应,处于假死状态。

2)jstat

这是jdk命令中比较重要,也是相当实用的一个命令,可以观察到classloader,compiler,gc相关信息

具体参数如下:

-class:统计class loader行为信息

-compile:统计编译行为信息

-gc:统计jdk gc时heap信息

-gccapacity:统计不同的generations(包括新生区,老年区,permanent区)相应的heap容量情况

-gccause:统计gc的情况,(同-gcutil)和引起gc的事件

-gcnew:统计gc时,新生代的情况

-gcnewcapacity:统计gc时,新生代heap容量

-gcold:统计gc时,老年区的情况

-gcoldcapacity:统计gc时,老年区heap容量

-gcpermcapacity:统计gc时,permanent区heap容量

-gcutil:统计gc时,heap情况

-printcompilation:不知道干什么的,一直没用过。

一般比较常用的几个参数是:

sudo jstat -class 2083 1000 10 (每隔1秒监控一次,一共做10次)

查看当时的head情况

sudo jstat -gcutil  20683 2000

注:该图不是出错截取

出现时候截取的数据是gc已经完全没有处理了,因为没有加上full gc的日志所以不确定JVM GC 时间过长,导致应用暂停。

3)获取内存快照

Jdk自带的jmap可以获取内在某一时刻的快照

命令:jmap -dump:format=b,file=heap.bin

file:保存路径及文件名

pid:进程编号(windows通过任务管理器查看,linux通过ps aux查看)

dump文件可以通过MemoryAnalyzer分析查看,网址:http://www.eclipse.org/mat/,可以查看dump时对象数量,内存占用,线程情况等。

从上面的图可以看得出来对象没有内存溢出。

从上图我们可以明确的看出此项目的HashMap内存使用率比较高,因为我们的系统都是返回Map的数据结构所以占用比较高的内存是正常情况。

4).观察运行中的jvm物理内存的占用情况

观察运行中的jvm物理内存的占用情况,我们也可以用jmap命令。

参数如下:

-heap:打印jvm heap的情况

-histo:打印jvm heap的直方图。其输出信息包括类名,对象数量,对象占用大小。

-histo:live :同上,但是只答应存活对象的情况

-permstat:打印permanent generation heap情况

命令使用:

jmap -heap 2083

可以观察到New Generation(Eden Space,From Space,To Space),tenured generation,Perm Generation的内存使用情况

输出内容:

上图为tomcat应用出错前JVM的配置信息,可以明确的看到当时的信息:

MaxHeapSize堆内存大小为:3500M

MaxNewSize新生代内存大小:512M

PermSize永久代内存大小:192M

NewRatio设置年轻代(包括Eden和两个Survivor区)与年老代的比值(除去持久代)。设置为2,则年轻代与年老代所占比值为1:2,年轻代占整个堆栈的1/3。

SurvivorRatio设置年轻代中Eden区与Survivor区的大小比值。设置为8,则两个Survivor区与一个Eden区的比值为2:8,一个Survivor区占整个年轻代的1/10。

在New Generation中,有一个叫Eden的空间,主要是用来存放新生的对象,还有两个Survivor Spaces(from,to), 它们用来存放每次垃圾回收后存活下来的对象。在Old Generation中,主要存放应用程序中生命周期长的内存对象,还有个Permanent Generation,主要用来放JVM自己的反射对象,比如类对象和方法对象等。

从上面的图可以看出来JVM的新生代设置太小,可以看出应用的新生代区完全占满了,无法再往新生代区增加新的对象此时的这些对象都处于活跃状态,所以不会被GC处理,但是tomcat应用还在继续产生新的对象,这样就会导致OOM的发生,这就是导致tomcat假死的原因。

四.Tomcat假死其它情况

以下是网上资料说的tomcat假的情况:

1.应用本身程序的问题,造成死锁。

2.load 太高,已经超出服务的极限。

3.jvm GC 时间过长,导致应用暂停。

因为出错项目里面没有打出GC的处理情况,所以不确定此原因是否也是我项目tomcat假死的原因之一。

4.大量tcp 连接 CLOSE_WAIT

netstat -n | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}'

TIME_WAIT 48

CLOSE_WAIT 2228

ESTABLISHED 86

常用的三个状态是:ESTABLISHED 表示正在通信,TIME_WAIT 表示主动关闭,CLOSE_WAIT 表示被动关。

java假死_分析java进程假死相关推荐

  1. java 进程假死原因_分析java进程假死状况

    1 引言 1.1 编写目的 为了方便大家以后发现进程假死的时候能够正常的分析并且第一时间保留现场快照. 1.2编写背景 最近服务器发现tomcat的应用会偶尔出现无法访问的情况.经过一段时间的观察最近 ...

  2. java程序假死_分析一个常见的java多线程通信问题(假死现象)

    一件复杂的事,一个人如果不能做,两个人又做的不好,一群人就可能很好的解决了.对于线程来说也是,通过多个线程就能完成一个更复杂的功能,这就需要多个线程协作,协作就需要交流,但是交流总是会出问题的.在这篇 ...

  3. java visualvm 内存_【Java线程与内存分析工具】VisualVM与MAT简明教程

    前言 本文将简要介绍Java线程与内存分析工具VisualVM和MAT的使用,进一步的学习可参考官网或工具帮助(例如MAT:Help -> Welcome -> Tutorials),并在 ...

  4. java 转储快照分析_分析Java核心转储

    java 转储快照分析 在本文中,我将向您展示如何调试Java核心文件,以查看导致JVM崩溃的原因. 我将使用在上一篇文章: 生成Java Core Dump中生成的核心文件. 您可以通过以下几种方法 ...

  5. java 类文件分析_分析Java .class文件

    这章的一个例子虽然简单,但是我觉的很有一定代表性.例子如下: 1:class Act { 2:   public static void doMathForever(int m) { 3:      ...

  6. java逻辑测试题_《Java理解程序逻辑试题分析》

    1.以下关于开发java程序的描述错误的是 (). (选择一项) A:开发Java程序的步骤包括:编写源程序.编译.运行 B:编写的Java源程序文件使用 java作为扩展名 C:Java源文件经编译 ...

  7. java 线程转储_获取Java线程转储的常用方法(推荐)

    1. 线程转储简介 线程转储(Thread Dump)就是JVM中所有线程状态信息的一次快照. 线程转储一般使用文本格式, 可以将其保存到文本文件中, 然后人工查看和分析, 或者使用工具/API自动分 ...

  8. 纯java分布式内存数据库_最新Java岗面试清单:分布式+Dubbo+线程+Redis+数据库+JVM+并发...

    最近可能有点闲的慌,没事就去找面试面经,整理了一波面试题.我大概是分成了Java基础.中级.高级,分布式,Spring架构,多线程,网络,MySQL,Redis缓存,JVM相关,调优,设计模式,算法与 ...

  9. ncs java 成都 面试_成都java工程师面试一般都是哪些问题,基础难不难!

    了解了许多学员参加的Java面试,他们表示,面试官提出的基础性问题还是比较多.从这个突破口切入,Java新手想要成功通过面试,基础知识方面也需要准备,今天达内成都Java培训班小编就来给大家分享一些J ...

最新文章

  1. 依赖注入_引用其他的bean
  2. what??|诞生才一年的BCH竟面临硬分叉的抉择
  3. Java操作——获取文件扩展名,去掉文件扩展名
  4. 成就优秀程序员的很多因素你知道多少?
  5. 多进程,守护进程,锁
  6. 一小时后关机_固始一女孩被塑料框“咬手” ,近1个小时后…
  7. 双网卡同时上内外网的解决方法
  8. 使用python,爆破加密的rar压缩文件
  9. 3dmax塌陷在哪里?怎么用?
  10. python正则匹配数字_python——正则匹配数字
  11. centos7利用libreoffice将doc文件转换为pdf
  12. 计算机基础内容相关的论文,有关于计算机基础论文范文
  13. 怎样给计算机桌面设密码,怎样给电脑设置锁屏密码
  14. 爱思服务器可以下小组件,iOS14 小组件添加/删除方法教程
  15. mysql主从配置duxi_Mysql主从同步配置
  16. linux 黑屏后死机,如何修复各种各样的黑屏死机
  17. wait()、notify()、notifyAll()使用详解
  18. 计算机专业英语职高 试卷,2020年河南高职单招英语样卷及答案分享
  19. 新冠疫情可视化(7月9日,7月10日)
  20. 【算法浅析NO.00004】递归算法浅析(un-accomplished version) by arttnba3

热门文章

  1. IP地址的基本换算实例
  2. 二叉树的六种遍历方法汇总(转)
  3. 挂在windows2003下的硬盘分区文件系统被系统识别为RAW,如何恢复至NTFS
  4. iPhoneUI元素的大小
  5. 蚂蚁变大象:浅谈常规网站是如何从小变大的(转)
  6. zend 修改默认view路径,添加扩展view
  7. windows的几个原则
  8. 政府门户网站建设解决方案
  9. k8s operator开发脚手架kubebuilder 3.2.0安装脚本整理
  10. Linux sed替换内容中有空格解决办法