Skip to content

Latest commit

 

History

History
83 lines (74 loc) · 4.99 KB

JVM-FineTuning.md

File metadata and controls

83 lines (74 loc) · 4.99 KB

JVM 是怎么去调优的?简述过程和调优的结果

1. JVM调优工具

JVM工具介绍

Jconsole,jProfile,VisualVM

  • Jconsole : jdk自带,功能简单,但是可以在系统有一定负荷的情况下使用。对垃圾回收算法有很详细的跟踪。
  • JProfiler:商业软件,需要付费。功能强大。
  • VisualVM:JDK自带,功能强大,与JProfiler类似。推荐。

如何定位问题

  • 观察内存释放情况、集合类检查、对象树

上面这些调优工具都提供了强大的功能,但是总的来说一般分为以下几类功能

  • 堆信息查看,可以查看下面的信息:

    • 可查看堆空间大小分配(年轻代、年老代、持久代分配)
    • 提供即时的垃圾回收功能
    • 长时间监控回收情况
    • 通过查看上面的信息判断是否存在下面几个方面问题:
      • 年老代年轻代大小划分是否合理
      • 内存泄漏
      • 垃圾回收算法设置是否合理
  • 线程监控

    • 线程信息监控:系统线程数量。
    • 线程状态监控:各个线程都处在什么样的状态下
    • Dump线程详细信息:查看线程内部运行情况
    • 死锁检查
  • 热点分析

    • CPU热点:检查系统哪些方法占用的大量CPU时间
    • 内存热点:检查哪些对象在系统中数量最大(一定时间内存活对象和销毁对象一起统计)
    • 可以根据找到的热点,有针对性的进行系统的瓶颈查找和进行系统优化
  • 快照

    • 快照是系统运行到某一时刻的一个定格。在我们进行调优的时候,不可能用眼睛去跟踪所有系统变化,依赖快照功能,我们就可以进行系统两个不同运行时刻,对象(或类、线程等)的不同,以便快速找到问题
    • 例如:系统进行垃圾回收以后,是否还有该收回的对象被遗漏下来的了。那么,我可以在进行垃圾回收前后,分别进行一次堆情况的快照,然后对比两次快照的对象情况。

内存泄漏(OOM)检查

内存泄漏是比较常见的问题,一般可以理解为系统资源(各方面的资源,堆、栈、线程等)在错误使用的情况下,导致使用完毕的资源无法回收(或没有回收),从而导致新的资源分配请求无法完成,引起系统错误。

  1. 堆空间被占满
  • 异常: java.lang.OutOfMemoryError: Java heap space
  • 问题: 堆内存泄漏,即所有堆空间都被无法回收的垃圾对象占满,虚拟机无法再在分配新空间。
  • 解决方案:
    • 抓取垃圾回收前后heap dump情况对比,
    • 同时根据对象引用情况(常见的集合对象引用)分析,基本都可以找到内存大户,
    • 再根据占用对象确定是否因为错误导致内存未释放,或者数据多导致内存溢出。
    • 最后根据原因fix bug.
  1. 持久代被占满
  • 异常:java.lang.OutOfMemoryError: PermGen space
  • 问题: Perm空间存放类信息、静态变量、常量等信息。它被占满主要是因为加载的类太多或者反射的类太多,导致无法为新的class分配存储空间而引发的异常。
    • 这个异常以前是没有的,但是在Java反射大量使用的今天这个异常比较常见了。主要原因就是大量动态反射生成的类不断被加载,最终导致Perm区被占满。
  • 解决方案:
    1. -XX:MaxPermSize=16m
    2. 换用JDK。比如JRocket。
  1. 堆栈溢出
  • 异常:java.lang.StackOverflowError
  • 问题::一般是递归太深、递归没返回、方法调用层数过多或者循环调用造成
  • 解决方案:修改代码,把递归改成非递归等。
  1. 线程堆栈满
  • 异常:Fatal: Stack size too small
  • 问题:java中一个线程的空间大小是有限制的。JDK5.0以后这个值是1M。与这个线程相关的数据将会保存在其中。但是当线程空间满了以后,将会出现上面异常。
  • 解决:增加线程栈大小。-Xss2m。但这个配置无法解决根本问题,还要看代码部分是否有造成泄漏的部分
  1. 系统内存被占满
  • 异常:java.lang.OutOfMemoryError: unable to create new native thread
  • 问题:这个异常是由于操作系统没有足够的资源来产生这个线程造成的。当线程数量大到一定程度以后,堆中或许还有空间,但是操作系统分配不出资源来了,就出现这个异常了。
  • 解决方案:
    1. 重新设计系统减少线程数量。
    2. 线程数量不能减少的情况下,通过-Xss减小单个线程大小。以便能生产更多的线程。

JVM 几个重要的参数


-server -Xmx3g -Xms3g -XX:MaxPermSize=128m 
-XX:NewRatio=1  #eden/old 的比例
-XX:SurvivorRatio=8  #s/e的比例 
-XX:+UseParallelGC 
-XX:ParallelGCThreads=8  
-XX:+UseParallelOldGC  #这个是JAVA 6出现的参数选项 
-XX:LargePageSizeInBytes=128m #内存页的大小,不可设置过大,会影响Perm的大小。 
-XX:+UseFastAccessorMethods #原始类型的快速优化 
-XX:+DisableExplicitGC  #关闭System.gc()