Jconsole,jProfile,VisualVM
- Jconsole : jdk自带,功能简单,但是可以在系统有一定负荷的情况下使用。对垃圾回收算法有很详细的跟踪。
- JProfiler:商业软件,需要付费。功能强大。
- VisualVM:JDK自带,功能强大,与JProfiler类似。推荐。
- 观察内存释放情况、集合类检查、对象树
上面这些调优工具都提供了强大的功能,但是总的来说一般分为以下几类功能
-
堆信息查看,可以查看下面的信息:
- 可查看堆空间大小分配(年轻代、年老代、持久代分配)
- 提供即时的垃圾回收功能
- 长时间监控回收情况
- 通过查看上面的信息判断是否存在下面几个方面问题:
- 年老代年轻代大小划分是否合理
- 内存泄漏
- 垃圾回收算法设置是否合理
-
线程监控
- 线程信息监控:系统线程数量。
- 线程状态监控:各个线程都处在什么样的状态下
- Dump线程详细信息:查看线程内部运行情况
- 死锁检查
-
热点分析
- CPU热点:检查系统哪些方法占用的大量CPU时间
- 内存热点:检查哪些对象在系统中数量最大(一定时间内存活对象和销毁对象一起统计)
- 可以根据找到的热点,有针对性的进行系统的瓶颈查找和进行系统优化
-
快照
- 快照是系统运行到某一时刻的一个定格。在我们进行调优的时候,不可能用眼睛去跟踪所有系统变化,依赖快照功能,我们就可以进行系统两个不同运行时刻,对象(或类、线程等)的不同,以便快速找到问题
- 例如:系统进行垃圾回收以后,是否还有该收回的对象被遗漏下来的了。那么,我可以在进行垃圾回收前后,分别进行一次堆情况的快照,然后对比两次快照的对象情况。
内存泄漏是比较常见的问题,一般可以理解为系统资源(各方面的资源,堆、栈、线程等)在错误使用的情况下,导致使用完毕的资源无法回收(或没有回收),从而导致新的资源分配请求无法完成,引起系统错误。
- 堆空间被占满
- 异常: java.lang.OutOfMemoryError: Java heap space
- 问题: 堆内存泄漏,即所有堆空间都被无法回收的垃圾对象占满,虚拟机无法再在分配新空间。
- 解决方案:
- 抓取垃圾回收前后heap dump情况对比,
- 同时根据对象引用情况(常见的集合对象引用)分析,基本都可以找到内存大户,
- 再根据占用对象确定是否因为错误导致内存未释放,或者数据多导致内存溢出。
- 最后根据原因fix bug.
- 持久代被占满
- 异常:java.lang.OutOfMemoryError: PermGen space
- 问题: Perm空间存放类信息、静态变量、常量等信息。它被占满主要是因为加载的类太多或者反射的类太多,导致无法为新的class分配存储空间而引发的异常。
- 这个异常以前是没有的,但是在Java反射大量使用的今天这个异常比较常见了。主要原因就是大量动态反射生成的类不断被加载,最终导致Perm区被占满。
- 解决方案:
- -XX:MaxPermSize=16m
- 换用JDK。比如JRocket。
- 堆栈溢出
- 异常:java.lang.StackOverflowError
- 问题::一般是递归太深、递归没返回、方法调用层数过多或者循环调用造成
- 解决方案:修改代码,把递归改成非递归等。
- 线程堆栈满
- 异常:Fatal: Stack size too small
- 问题:java中一个线程的空间大小是有限制的。JDK5.0以后这个值是1M。与这个线程相关的数据将会保存在其中。但是当线程空间满了以后,将会出现上面异常。
- 解决:增加线程栈大小。-Xss2m。但这个配置无法解决根本问题,还要看代码部分是否有造成泄漏的部分
- 系统内存被占满
- 异常:java.lang.OutOfMemoryError: unable to create new native thread
- 问题:这个异常是由于操作系统没有足够的资源来产生这个线程造成的。当线程数量大到一定程度以后,堆中或许还有空间,但是操作系统分配不出资源来了,就出现这个异常了。
- 解决方案:
- 重新设计系统减少线程数量。
- 线程数量不能减少的情况下,通过-Xss减小单个线程大小。以便能生产更多的线程。
-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()