1)调优的工具:
Jconsole,jProfile,VisualVM
Jconsole: jdk自带,功能简单,但是可以在系统有一定负荷的情况下使用。对垃圾回收算法有很详细的跟踪。
JProfiler:商业软件,需要付费。功能强大。
VisualVM:JDK自带,功能强大,与JProfiler类似。
2)如何调优
观察内存释放情况,集合类检查,对象数等。
上面这些调优工具都提供了强大的功能,但是总的来说一般分为以下几类功能:
(1)堆信息查看
查看的内容包括:堆空间大小分配(年轻代,年老代,持久代分配),垃圾监控,查看堆中类、对象的信息,对象引用情况。
利用堆信息可以解决:年老代,年轻代内存大小的划分,内存泄漏,垃圾回收算法是否合理。
(2)线程监控
监控内容:线程信息监控,系统线程数量,线程状态监控,Dump线程详细信息(线程内部运行情况),死锁检查。
(3)热点分析
CPU热点:检查系统哪些方法占用的大量CPU时间
内存热点:检查哪些对象在系统中数量最大(一定时间内存活对象和销毁对象一起统计)
快照:是系统运行到某一时刻的定格。
(4)内存泄漏
内存泄漏一般可以理解为系统资源(各方面的资源,堆、栈、线程等)在错误使用的情况下,导致使用完毕的资源无法回收(或没有回收),从而导致新的资源分配请求无法完成,引起系统错误。
内存泄漏和系统超负荷两者是有区别的,虽然可能导致的最终结果是一样的。内存泄漏是用完的资源没有回收引起错误,而系统超负荷则是系统确实没有那么多资源可以分配了(其他的资源都在使用)。
(5)调优典型例子
1.年老代堆空间被占满。这是最典型的内存泄漏方式,简单说就是所有堆空间都被无法回收的垃圾对象占满,虚拟机无法再在分配新空间。
解决方法:这种方式解决起来也比较容易,一般就是根据垃圾回收前后情况对比,同时根据对象引用情况(常见的集合对象引用)分析,基本都可以找到泄漏点。
2.持久代被占满:
解决方法:(1. -XX:MaxPermSize=16m
(2. 换用JDK。比如JRocket。
3.堆栈溢出(一般是由递归或循环造成的)
增加线程栈大小。-Xss2m。但这个配置无法解决根本问题,还要看代码部分是否有造成泄漏的部分。
4.系统内存被占满
(1. 重新设计系统减少线程数量。
(2. 线程数量不能减少的情况下,通过-Xss减小单个线程大小。以便能生产更多的线程。