• 性能测试之 JVM 异常说明和分析工具


    StackOverflowError和OutOfMemoryError是JVM里的两种Error。每个运行时区域——程序计数器
    、Java虚拟机栈、本地方法栈、Java堆、方法区、直接内存发生Error的原因和错误信息是不同的。

    不是所有的StackOverflowError和OutOfMemoryError都需要调整参数,要做到正确分析、合理调整

    常见异常说明

    Java堆溢出

    1. 关键错误信息
    java.lang.OutOfMemoryError:java heap space 
    
    1. 排查思路

      检查Java虛拟机的堆参数设置,与机器的内存对比,看看是否还有向上调整的空间。再从代码上检查是否存在某些对象生命周期过长、持有状态时间过长、存储结构设计不合理等情况,尽量减少程序运行期的内存消耗。

    2. 参数配置

    -Xmx 最大堆大小 默认物理内存的1/64
    -Xms 初始堆大小 默认物理内存的1/4(<1GB)	
    

    栈溢出

    HotSpot虚拟机栈=虚拟机栈+本地方法栈

    1. 错误信息
    java.lang.StackOverflowError
    java.lang.OutOfMemoryError
    
    1. 排查思路

      出现StackOverflowError异常时,会有明确错误堆栈可供分析,相对而言比较容易定位到问题所在。

      如果是建立过多线程导致的OutOfMemoryError,在不能减少线程数量或者更换64位虚拟机的情况下,就只能通过减少最大堆和减少栈容量来换取更多的线程,通过“减少内存”的手段来解决内存溢出。
    2. 参数配置
    -Xss 每个线程堆栈的大小。一般情况下256K是足够了。影响此进程中并发线程数大小等。
    

    方法区溢出

    1. 错误信息
    JDK1.7以前的错误信息
    java.lang.OutOfMemoryError: PermGen space
    
    1. 排查思路
      JDK1.7起,原本存放在永久代的字符串常量池被移至Java堆之中,所以在JDK7及以上版本,限制方法区的容量对该测试用例来说是毫无意义的。

      在JDK1.8以后,永久代便完全退出了历史舞台,元空间作为其替代者登场。
    2. 参数配置
    <= JDK1.6
    -XX:PermSize
    -XX:MaxPermSize
    >= JDK1.8
    -XX:MetaspaceSize
    -XX:MaxMetaspaceSize 元空间最大值,默认是-1,即不限制,或者说只受限于本地内存大小。
    
    

    直接内存溢出

    1. 错误信息
    java.lang.OutOfMemoryError
    
    1. 排查思路

      由直接内存导致的内存溢出,一个明显的特征是在HeapDump文件中不会看见有什么明显的异常情况,如果读者发现内存溢出之后产生的Dump文件很小,而程序中又直接或间接使用了
      DirectMemory ( 典型的间接使用就是NIO),那就可以考虑重点检查一下直接内存方面的原因了。
    2. 参数配置
    -XX:MaxDirectMemorySize 默认与Java堆最大值(由-Xmx指定)一致
    

    JDK自带的分析工具

    jps    JVM Process Status Tool    显示指定系统内所有的HotSpot虚拟机进程
    jinfo  Configuration Info for Java    显示虚拟机配置信息
    jmap   JVM Memory Map    生成虚拟机的内存转储快照,生成heapdump文件
    jhat   JVM Heap Dump Browser    用于分析heapdump文件,它会建立一个HTTP/HTML服务器,让用户在浏览器上查看分析结果
    jstat  JVM Statistics Monitoring Tool    用于收集Hotspot虚拟机各方面的运行数据
    jstack JVM Stack Trace    显示虚拟机的线程快照
    

    jstat

    可以显示本地或者远程虛拟机进程中的类加载、内存、垃圾收集、即时编译等运行时数据,在没有GUI图形界面、只提供了纯文本控制台环境的服务器上,是运行期定位虚拟机性能问题的常用工具。

    -class
    监视类加载、卸载数量、总空间以及类装载所耗费的时间
    -gc
    监视Java堆状况,包括Eden区、2个Survivor区、老年代、永久代等的容量,已用空间,垃圾收集时间合计等信息
    -gccapacity
    监视内容与-gc基本相同,但输出主要关注Java堆各个区域使用到的最大、最小空间
    -gcutil
    监视内容与-gc基本相同,但输出主要关注已使用空间占总空间的百分比
    -gccause
    与-gcutil功能--样,但是会额外输出导致上一次垃圾收集产生的原因
    -gcnew
    监视新生代垃圾收集状况
    -gcnewcapacity
    监视内容与-gcnew基本相同,输出主要关注使用到的最大、最小空间
    -gcold
    监视老年代垃圾收集状况
    -gcoldcapacity
    监视内容与-gcold基本相同,输出主要关注使用到的最大、最小空间
    -gcpermcapacity
    输出永久代使用到的最大、最小空间
    -compiler
    输出即时编译器编译过的方法、耗时等信息
    -printcompilation
    输出已经被即时编译的方法
    

    jstack

    可以生成虚拟机当前时刻的线程快照(-般称为threaddump或者javacore文件)。线程快照就是当前虚拟机内每-条线程正在执行的方法堆栈的集合,生成线程快照的目的通常是定位线程出现长时间停顿的原因,如线程间死锁、死循环、请求外部资源导致的长时间挂起等,都是导致线程长时间停顿的常见原因。线程出现停顿时通过jstack来查看各个线程的调用堆栈,就可以获知没有响应的线程到底在后台做些什么事情,或者等待着什么资源。

    jstack -l 进程ID  
    除堆栈外显示关于锁的附加信息
    

    扫一扫,关注我

  • 相关阅读:
    Object-c的类可以多重继承么?可以实现多个接口么?如何实现?
    对于TableViewCell重用机制的理解
    xcode快捷方式
    Mysql数据迁移——按分号split一列字段插入另一张表
    Android手机导出微信聊天记录
    Java性能分析工具之Jprofiler初体验
    Android adb端口被占用的解决办法
    mysql limit查询性能优化
    Delphi异或算法转换为java实现
    [python]用Python进行SQLite数据库操作
  • 原文地址:https://www.cnblogs.com/hally/p/13169439.html
Copyright © 2020-2023  润新知