架构师成长之路我爱编程

JVM异常处理

2018-04-13  本文已影响19人  一一道长一一

JVM监控和管理主要针对的是JVM内存溢出问题和性能问题,本篇主要介绍JVM常见的异常处理方式和性能调优。


一、OutOfMemoryError异常

要监控JVM的各种OutOfMemoryError,首先需要配置VM Args(虚拟机启动参数),各IDE在类的启动页面都有相应配置,这里主要用到的是:-Xms10M -Xmx10m -XX:+HeapDumpOnOutOfMemoryError -XX:+PrintGC -XX:+PrintGCDetails,参数意义参考JVM垃圾回收文章末尾,以下列出了常见的异常信息对应的溢出点:

异常 溢出点
java.lang.StackOverflowError 虚拟机栈溢出
java.lang.OutOfMemoryError: Java heap space 堆溢出
java.lang.OutOfMemoryError: unable to create new native thread 本地方法栈溢出
java.lang.OutOfMemoryError: GC overhead limit exceeded java8中不存在方法区和运行时常量池溢出,而是会抛出这个异常,因GC次数过多,可通过UseGCOverheadLimit参数来关闭,但是不建议这么做
java.lang.OutOfMemoryError(无其他异常信息) 可能是本机直接内存溢出

二、JDK自带监控和故障处理工具

在jdk安装的bin目录中,JDK提供了很多强大的工具,具体用法可以从网上找,太多了就不一一展开了:

  1. 命令行工具
名称 作用
jps 显示指定系统内所有的HotSpot虚拟机进程,最常用
jstat 用户手机HotSpot虚拟机各方面的运行数据
jinfo 显示虚拟机运行配置
jmap 生成虚拟机的内存转储快照(heapdump文件)
jhat 用户分析heapdump文件,它会建立一个HTTP/HTML服务器,让用户可以在浏览器上查看分析结果
jstack 显示虚拟机的内存快照

PS:使用-h或-help查看每个命令的具体用法

  1. 图形化工具
名称 作用
jconsole Java监视与管理控制台
jvisualvm 多合一故障处理工具

三、理解GC日志

以下边这段GC日志为例

[GC [PSYoungGen: 1964K->490K(2560K)] 1964K->746K(9728K), 0.0147978 secs] [Times: user=0.05 sys=0.00, real=0.02 secs] 
[Full GC [PSYoungGen: 490K->0K(2560K)] [ParOldGen: 256K->712K(7168K)] 746K->712K(9728K), [Metaspace: 3275K->3275K(1056768K)], 0.0102199 secs] [Times: user=0.06 sys=0.00, real=0.01 secs] 
Heap
 PSYoungGen      total 2560K, used 20K [0x00000000ffd00000, 0x0000000100000000, 0x0000000100000000)
  eden space 2048K, 1% used [0x00000000ffd00000,0x00000000ffd05360,0x00000000fff00000)
  from space 512K, 0% used [0x00000000fff00000,0x00000000fff00000,0x00000000fff80000)
  to   space 512K, 0% used [0x00000000fff80000,0x00000000fff80000,0x0000000100000000)
 ParOldGen       total 7168K, used 712K [0x00000000ff600000, 0x00000000ffd00000, 0x00000000ffd00000)
  object space 7168K, 9% used [0x00000000ff600000,0x00000000ff6b22f0,0x00000000ffd00000)
 Metaspace       used 3282K, capacity 4496K, committed 4864K, reserved 1056768K
  class space    used 359K, capacity 388K, committed 512K, reserved 1048576K
  1. 日志开头的[GC 和 [Full GC ,说明这次垃圾收集的停顿类型,如果是Full GC,说明这里发生了Stop The World(用户线程完全停止)
  2. 下来的[PSYoungGen 说明了GC发生的区域(新生代还是老年代),名字跟使用的垃圾收集器相关
  3. 方括号中的1964K->490K(2560K) 的意思是“GC前该区域使用的容量->GC后该区域使用的容量(该区域的总容量)”,比如上边这个的意思就是PS收集器的新生代的区域中GC前使用了1964K的容量,GC后使用的容量为490k,新生代区域总共有2560k的容量
  4. 方括号外的1964K->746K(9728K)的意思是“GC前java堆中使用的容量->GC后java堆中使用的容量(java堆的总容量)”
  5. 0.0147978 secs 表示本次GC的耗时,系统经常停顿时的主要观察对象
  6. Heap之后的内容为PrintGCDetails打印的内容,详细显示了java堆中各个区域的大小

完整的格式为:[GC类型 [GC发生的区域: 该区域GC前使用的容量 -> 该区域GC后使用的容量(该区域的总容量) ] GC前java堆中使用的容量 -> GC后java堆中使用的容量(java堆的总容量), GC所占的时间] [Times: user=用户态消耗的CPU时间 sys=内核态消耗的CPU时间, real=GC从开始到结束所经过的墙钟时间]
PS:墙钟时间包含各种非运算的等待耗时,包括磁盘I/O,线程加载等


有了工具和日志信息,就很容易下手了,具体症状还要具体分析,这里就不一一举例了(其实就是懒的写了)。

上一篇下一篇

猜你喜欢

热点阅读