JVM调优的几种场景

最近一段时间都在学习中度过,之前一直在说JVM调优的问题,但是一直没有实际操作过,今天结合学习的知识和实操,进行一个简单的记录,希望也能帮助到需要的小伙伴。

一、CPU占用过高

   cup过高需要分情况来进行分析,如,是不是业务在搞活动,突然大批量的流量进来了,
   而且当活动结束后cpu占用率下来了,如果是这种情况的话就不用关关心了,因为请求越多,
   需要处理的线程数越多,这是正常的现象。
  (如果服务器的配置不高,如cpu只有1核,这种情况稍微流量大点就会把cpu打满,这时我们优先考虑升级配置)。

1、可以使用top命令查看cpu占用情况在这里插入图片描述

这样就可以定位出cpu过高的进程。在linux下,top命令获得的进程号和jps工具获得的vmid是相同的:
在这里插入图片描述

2、用top -Hp命令查看线程的情况

top -Hp 7268

在这里插入图片描述
可以看到是线程id为7287这个线程一直在占用cpu

3、把线程号转换为16进制

 printf "%x" 7287

在这里插入图片描述

4、用jstack工具查看线程栈情况

jstack 7268 | grep 1c77 -A 10

在这里插入图片描述
通过jstack工具输出现在的线程栈,再通过grep命令结合上一步拿到的线程16进制的id定位到这个线程的运行情况,其中jstack后面的7268是第1步定位到的进程号,grep后面的是2、3步定位到的线程号。
从输出结果可以看到这个线程处于运行状态,在执行com.spareyaya.jvm.service.EndlessLoopService.service这个方法,代码行号是19行,这样就可以去到代码的19行,找到其所在的代码块,看看是不是处于循环中,这样就定位到了问题。

二、死锁

一般的web项目都是多线程的应用,它服务于多个请求,程序发生死锁后,死锁的线程进入等待状态,并不占用cpu,消耗的内存也很少,最后会出现请求超时,在死锁的情况不多的时候,这种情况不容易被发现。
可以使用jstack工具查看

1、jps 查看所以的进程

jps -l

在这里插入图片描述

2、jstack查看死锁问题

由于web应用往往会有很多工作线程,特别是在高并发的情况下线程数更多,于是这个命令的输出内容会十分多。jstack最大的好处就是会把产生死锁的信息(包含是什么线程产生的)输出到最后,所以我们只需要看最后的内容就行了。
在这里插入图片描述
发现了一个死锁,原因也一目了然。

内存泄漏

程序发生内存泄漏后,进程的可用内存会慢慢变少,最后的结果就是抛出OOM错误。发生OOM错误后可能会想到是内存不够大,于是把-Xmx参数调大,然后重启应用。这么做的结果就是,过了一段时间后,OOM依然会出现。最后无法再调大最大堆内存了,结果就是只能每隔一段时间重启一下应用。
内存泄漏的另一个可能的表现是请求的响应时间变长了。这是因为频繁发生的GC会暂停其它所有线程(Stop The World)造成的。
为了模拟这个场景,使用了以下的程序:
在这里插入图片描述

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class Main {

    public static void main(String[] args) {
        Main main = new Main();
        while (true) {
            try {
                Thread.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            main.run();
        }
    }

    private void run() {
        ExecutorService executorService = Executors.newCachedThreadPool();
        for (int i = 0; i < 10; i++) {
            executorService.execute(() -> {
                // do something...
            });
        }
    }
}

1、用jps定位到进程号

在这里插入图片描述
因为已经知道了是哪个应用发生了OOM,这样可以直接用jps找到进程号135988

2、用jstat分析gc活动情况

jstat是一个统计java进程内存使用情况和gc活动的工具,参数可以有很多,可以通过jstat -help查看所有参数以及含义`jstat -gcutil -t -h8 24836`
![在这里插入图片描述](https://img-blog.csdnimg.cn/a62d2285640c4afeab317a62f022fbcc.png)
  上面是命令意思是输出gc的情况,输出时间,每8行输出一个行头信息,统计的进程号是24836,每1000毫秒输出一次信息。
 输出信息是Timestamp是距离jvm启动的时间,S0、S1、E是新生代的两个Survivor和Eden,O是老年代区,M是Metaspace,CCS使用压缩比例,YGC和YGCT分别是新生代gc的次数和时间,FGC和FGCT分别是老年代gc的次数和时间,GCT是gc的总时间。虽然发生了gc,但是老年代内存占用率根本没下降,说明有的对象没法被回收(当然也不排除这些对象真的是有用)。

3、用jmap工具dump出内存快照

 jmap可以把指定java进程的内存快照dump出来,效果和第一种处理办法一样,不同的是它不用等OOM就可以做到,而且dump出来的快照也会小很多。
jmap -dump:live,format=b,file=heap.bin 24836
这时会得到heap.bin的内存快照文件,然后就可以进行分析了,比如使用JProfiler、MAT等,这里就不做对应的分析了。

总结:

以上三种严格地说还算不上jvm的调优,只是用了jvm工具把代码中存在的问题找了出来。我们进行jvm的主要目的是尽量减少停顿时间,提高系统的吞吐量。但是如果我们没有对系统进行分析就盲目去设置其中的参数,可能会得到更坏的结果,jvm发展到今天,各种默认的参数可能是实验室的人经过多次的测试来做平衡的,适用大多数的应用场景。如果你认为你的jvm确实有调优的必要,也务必要取样分析,最后还得慢慢多次调节,才有可能得到更优的效果。
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值