一般在系统出现问题的时候,我们会考虑对 JVM 进行性能优化。优化思路就是根据问题的情况,结合工具进行问题排查,针对排查出来的可能问题找到对应的解决方案。

1

JVM 优化思路

JVM 性能优化思路_堆内存

1、系统中可能会出现的问题

1、OOM:OOM是指Java虚拟机在启动或运行过程中,无法申请到足够的内存空间,导致抛出java.lang.OutOfMemoryError。

OOM产生的原因可能有以下几点:

(1)代码中存在大对象分配。

(2)内存泄露,导致在多次GC之后,还是无法找到一块足够大的内存容纳当前对象。

(3)永久代/元空间设置的过小。

(4)应用长时间运行,没有重启,运行期间生成了大量的类。

2、死锁:死锁是指两个或两个以上的进程或线程,在执行过程中,由于竞争资源而造成的一种阻塞的现象,若无外力作用,它们都将无法继续执行。

3、CPU 飙升:CPU飙升是指程序运行时CPU占用率过高。

CPU飙升的可能原因如下:

(1)系统负载高:负载高表示有很多程序等待调度运行,它会导致上下文切换频繁。

(2)大量并发的I/O操作。

(3)多线程抢占系统资源。

4、线程池不够用:线程池不够用指的是当前线程数小于核心线程数,但已提交的任务个数大于当前线程数,这时线程池中的线程无法满足任务的需求,需要创建新的线程来执行任务。

5、GC 次数频繁:GC次数频繁是指程序运行时Full GC的次数超过了可接受的正常水平。

2、问题排查的手段

(1)用 jmap 命令 dump 出堆文件,利用 MAT 工具分析

(2)用 jstack 命令查看线程堆栈信息

(3)用 top 命令查看占用 CPU 高的进程,结合 jps,jinfo,jstat,jmap 等命令分析原因

(4)用 jvisualvm、jconsole、arthas 等工具查看 JVM 状态

(5)开启 GC 日志打印,结合 GCViewer 分析 GC 日志,查看 GC 执行情况

3、常用的解决方案

(1)适当增加堆内存大小

(2)选择合适的垃圾收集器

(3)代码中及时释放资源

(4)合理设置线程池的参数

(5)集群部署增加负载能力

(6)利用 MQ 进行异步削峰

(7)综合利用本地缓存、Redis 缓存减少数据库压力

2

常用问题分析思路

JVM 性能优化思路_堆内存_02

1、OOM 问题

导出 dump 文件,然后用 MAT 或者其他工具分析 dump 文件,分析为什么内存使用高了,我们可以适当增加堆内存的空间,也可以适当的减少并发数,增加消息队列来解决等。

2、CPU 飙升问题

使用 top 命令找到 CPU 使用率高的进程,我们可以通过 jstack 查看线程情况,通过 jinfo 命令查看 JVM 参数,通过 jmap 命令查看堆内存,如果是业务代码问题(死锁、资源没释放),那么可以修改代码;如果是用户并发太高,那么可以增加集群数量来减轻服务器压力;如果是没有异步处理,那么可以使用消息队列等,如果是垃圾回收的线程一直占用 CPU,那么可以对 GC 进行优化。

3、GC 频繁问题

开启 GC 日志打印,使用 GCViewer 工具分析 GC 日志,查看 GC 执行情况,如果是堆内存空间的问题,那么我们可以适当增加堆内存的空间,比如调高新生代空间;如果是垃圾收集器设置的不合适,我们可以选择合适的垃圾收集器,比如大内存空间可以选择 G1;如果使用 G1 收集器,暂停时间设置的太小,我们可以把暂停时间适当调大一点,初始堆内存设置的太小,我们可以适当调大一点初始堆内存设置等。

后面将为大家介绍常见的 JVM 面试题分析