JVM调优的原则?
- 不要为了调优而调优,首先确定的应该是项目的架构与代码已经没有优化的空间了,再考虑进行JVM的调优工作,不能指望通过JVM调优来使得性能有一个质的飞越
- 从三个属性中(吞吐量,延迟,内存)中选择两个进行JVM调优,称之为调优3选2,在处理吞吐量和延迟问题时,GC能使用的内存越大,应用运行也就越流畅,这也叫GC内存最大化原则
什么情况下需要进行调优?
- Full GC数量频繁,GC停顿时间超长(超过1s)
- 应用出现OOM异常或者吞吐量下降,响应性能不高,
- 应用CPU占用过高,内存占用过高
吞吐量和低延迟?
吞吐量:代码时间/(代码时间+垃圾回收时间),吞吐量越高,算法越好
低延迟:STW越短,响应时间越好,算法越好,目的在于缩短或者完全消除因垃圾收集器引起的停顿
一个GC算法只可能针对于以上两个目标之一或者尝试找到一个折中方案,吞吐量优先的垃圾回收器有Parallel的年轻代和老年代版本,响应时间优先的垃圾回收器有CMS和G1
常用性能调优工具和常用参数
常用工具:jvisualvm,jconsole,MAT(提示可能内存泄露的点)
常用参数解释:
- -Xms:JVM启动时申请的初始Heap大小
- -Xmx:JVM运行时可申请的最大Heap值,为了避免每次GC后JVM重新分配内存,一般设置为同一个值
- -Xmn:设置Heap中新生代的大小,通过Xms-Xmn可以得到老年代的大小
- -Xss:设置每个线程可使用的栈大小
- -XX:TraceClassLoading/TraceClassUnLoading可以在日志中追踪类加载和卸载的情况
CPU占用过高的排查流程?
- top命令查看出cpu最高的进程pid(这里也可以用jps -l命令)
- [ps -mp 进程号 -o THREAD,tid,time]定位具体的线程(这里也可以使用top -Hp pid)
- 使用[printf "%x\n" 线程id]将需要的线程转换为16进制格式
- 使用[jstack 进程ID|grep 16进制线程id -A60]打印出前60行信息
ps常用参数:
-A 显示所有进程(等价于-e)(utility)
-a 显示一个终端的所有进程,除了会话引线
-N 忽略选择。
-d 显示所有进程,但省略所有的会话引线(utility)
-x 显示没有控制终端的进程,同时显示各个命令的具体路径。dx不可合用。(utility)
-p pid 进程使用cpu的时间
-u uid or username 选择有效的用户id或者是用户名
-g gid or groupname 显示组的所有进程。
-f 全部列出,通常和其他选项联用。如:ps -fa or ps -fx and so on.
-l 长格式(有F,wchan,C 等字段)
-j 作业格式
-o 用户自定义格式
-m 显示所有的线程
-H 显示进程的层次(和其它的命令合用,如:ps -Ha)(utility)
-a 显示同一终端下的所有程序
-A 列出所有的进程
-w 显示加宽可以显示较多的资讯
-au 显示较详细的资讯
-aux 显示所有包含其他使用者的进程
-e 显示所有进程,环境变量
-f 全格式
-h 不显示标题
-l 长格式
-w 宽输出
内存占用过高排查流程?
- 查找进程Id: top查看内存占用过高的进程pid
- [jmap -heap pid]:查看JVM堆内存的分配情况
- [jmap -histo:live pid|head -n 100]:查看占用内存比较多的存活对象
什么情况会抛出OOM?OOM之前会发生什么
满足以下两个条件中的任意一个会产生OOM
- JVM的98%时间都用于内存回收
- 每次回收的内存小于2%
OOM之前的现象:
- 每次垃圾回收的时间越来越长,且full gc的次数越来越多
- 老年代的内存越来越大,每次full gc后,只有少量的内存被释放掉
线上死锁排查?
- [jps -l]查找到可能有问题的进程id
- 执行[jstack -F 进程id]命令
- 如果说可以远程连接到JVM,可以使用jconsole或者jvisualvm,以图形化界面检测是否死锁
jstack命令:
-l:打印关于锁的信息
-F:当-l没有响应的时候,强制打印栈信息
-m:答应jaba和native c/c++框架所有栈信息
?
|