《十》JVM的调优

目录

什么叫调优?

命令

常用的命令跟踪Java进程有没有bug

jps        ——>        Java的进程显示

jinfo + 进程id        ——>        Java进程的一些相关信息

jstat        ——>        Java统计信息或数据跟踪信息

jstack        ——>        用来跟踪线程的

如果你的jvmCPU爆了,那么我怎么去查这个问题

jmap  

jhat

VisualVM工具


什么叫调优?

严格意思上来说:

  1. 根据需求进行jvm规划与预调优 (例如,我们规划每天要有100万的下单量,要用什么样的机器,要用多少内存)
  2. 优化进行jvm的环境(慢,卡顿)(这种情况要通过压测来定位到一个系统的瓶颈)
  3. 解决jvm在运行中出现的各种问题(Menmory Leak OOM)

现在有一段代码:

在银行体系或者互联网金融体系当中进行风控的模型,现在CardInfo里面是每个人的个人信息,getAllCardInfo()方法每次相当于在数据都读出100条数据,加入到任务列表里面,启动一个线程池,这个线程池它是固定时长固定频率的来执行任务的线程池,在这个线程池里面有50个线程,每隔100ms执行一个任务。如下:

package JVM.垃圾回收;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

public class GC_Problem01 {

    public static class CardInfo{
        BigDecimal price  = new BigDecimal(0.0);
        String name = "tde";
        int age = 5;
       Date birthdate = new Date();

       public void m(){}
    }

   private static ScheduledThreadPoolExecutor executor   = new ScheduledThreadPoolExecutor(50,new ThreadPoolExecutor.DiscardOldestPolicy());

    public static void main(String[] args) throws InterruptedException {
        executor.setMaximumPoolSize(50);
        for (;;){
            modelFit();
            Thread.sleep(100);
        }
    }


    private static void modelFit(){
        List<CardInfo> taskList = getAllCardInfo();
        taskList.forEach(
                t-> {
                    executor.scheduleWithFixedDelay(() -> {
                        t.m();
                    },2,3, TimeUnit.SECONDS);
                }
        );

    }

    private static List<CardInfo> getAllCardInfo(){
       List<CardInfo> taskList = new ArrayList<>();
    for (int i = 0; i < 100; i++ ) {
            CardInfo ci = new CardInfo();
        taskList.add(ci);
        }
    return taskList;
    }
}

D:\>java -Xms200M -Xmx200M -XX:+PrintGC 类名

-Xms200M最小堆大小

-Xmx200M最大堆大小

为什么都设为200M,不用扩容,防止内存抖动

-XX:+PrintGC :垃圾回收器的日志输出

 当运行起来的时候,这里显示目前产生了一次GC

GC产生的一次原因是Allocation Failure 分配失败

原本我的年轻代占了 54656k 垃圾回收一次为1074k 总的堆大小为 198016k 回收的时长为  0.0069533 secs

命令

当我们敲Java的命令的时候,它会启动一次Java虚拟机

 通常-开头的是标准参数 -X开头的是非标准参数

 所以在敲java -X的时候它会把Java的非标参数给输出出来,真正调优用到的是-XX开头的

 但是-XX开头的参数它是没有一个专门的文档给列出来

只能执行java -XX:+PrintFlagsFinal -version 打印所有参数的最终值   非常多

常用的命令跟踪Java进程有没有bug

jps        ——>        Java的进程显示

jps全称JVM Process Status Tool,一款查看java进程的工具。查看当前环境下运行的java服务的进程id和名称

jps

  • -q:只输出进程id

  • -m:输出虚拟机启动时传递给main()方法的参数

  • -l:输出主类的全名,如果执行的是jar包,输出jar包的路径

  • -v:输出启动虚拟机的参数

 jinfo + 进程id        ——>        Java进程的一些相关信息

Configuration info for Java,一款用于实时查看和修改JVM参数的工具。注意,如果是修改,参数类型是manageable类型才能修改。

jinfo PID
jinfo -flag name PID 查看某个java进程的name属性的值
jinfo -flags PID 查看已经复制的JVM参数

 jstat        ——>        Java统计信息或数据跟踪信息

jstat全称JVM Statistics Monitoring,一款用于监视虚拟机各种运行状态统计信息工具,主要显示如下信息:虚拟机进程的类装载、内存、垃圾收集、JIT编译等。

  • 查看类装载信息
jstat -class PID 1000 10 //查看某个Java进程的类装载信息,每1000毫秒输出一次,共输出10次

  • 查看垃圾收集信息
jstat -gc PID 1000 10

上图显示了各个区以及垃圾回收的情况,具体代表含义如下(C代表Capacity,U代表Used已使用大小)

  • S0C和S1C代表Survivor区的S0和S1的大小
  • S0U和S1U表示已使用空间
  • EC表示Eden区大小,EU表示Eden区已使用容量
  • OC表示老年代大小,OU代表老年代已使用容量
  • MC表示方法区大小,MU表示方法区已使用容量
  • CCSC表示压缩类空间大小,CCSU表示压缩类空间已使用大小
  • YGC表示新生代GC次数,YGT表示新生代GC总耗时
  • FGC表示Full GC次数,FGCT表示FULL GC总耗时
  • GCT表示GC总耗时时间

 jstack        ——>        用来跟踪线程的

Stack Trace for Java,一款用于生成当前时刻的线程状态信息的快照工具,这个对于分析当前线程状态非常有用,比如说是否有哪个线程阻塞了,或者说是否发生了死锁等信息。如:

jstack PID

jstack 9824 会把9824里面所有的线程 (线程名称,线程编号,线程优先级,线程状态,线程的调用堆栈) 

 如果很多线程await在一把锁上面,这个时候可能你的程序产生了死锁

如果你的jvmCPU爆了,那么我怎么去查这个问题

这需要查询是什么样的线程在占用CPU,执行系统级命令top 它会进程当前占用的CPU是多少

 想知道这个进程的某个线程占用的资源比较高,需要运行命令  top -Hp 11800 linux top命令 查看进程及相关线程信息

然后找到cpu资源大的查询它的线程信息 jstack  ,找到这个线程之后需要定位这个线程有两种情况:

  1. 线程为VM一般是GC,垃圾回收线程,如果是GC,他会CPU会不断地增高,这时候需要开发人员去读GC的日志,看看日志里面是不是在执行GC,原因是什么。
  2. 业务线程,去看业务线程掉了那个方法,看看是那个方法不断地循环占用CPU资源

 运行命令 top -Hp 11800

 会发现在不断地FGC,输出信息,内存回收每次回收20M,回收结束还剩20M,每次只回收了6K,这里频繁FGC就说明内存里面有资源被占用并且回收不掉。

频繁FGC怎么定位?

观察每次FGC每次回收的情况是否正常,200M回收还是200M,一定是内存被占用而且还回收不掉,还有引用指向。

jmap  

Memory Map for Java,一款用于生成堆转储快照即dump文件的命令

jmap -heap PID //打印出堆内存相关信息

jmap -dump:format=b,file=/usr/heap.hprof PID //生成dump文件

但是往外面导入文件依然会让jvm卡死不建议使用 

jmap -dump:format=b,file=/usr/heap.hprof PID   产生堆存储文件,当怀疑这个jvm有bug的时候,用这个命令可以让整个这块内存,导出来存储到硬盘中,存成一个文件 

-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=heap.hprof

上面常用参数可以设置,一旦发生OOM之后就会自动生成dump文件 

jhat

Jvm Heap Analysis Tool,一款用于分析dump文件的工具

jhat heap.hprof

然后访问地址,http://localhost:7000/ 可以看到这款工具展示的信息比较简单。 

进程号为8456, jmap -histo 8456,展示对应对象占了多少的字节

我的内存被占用了,并且回收不了对象就是这些对象造成的 

VisualVM工具


All-in-one Java TroubleshootingTool,是JDK发布的一款功能强大的运行监控故障处理工具。

  • 监控应用程序的CPU、GC、堆。方法区和线程信息(jstack和jstat的功能)
  • dump文件以及分析(jmap和jhat的功能)
  • 方法级的程序性能分析,可以找出被调用最多,运行时间最长的方法
  • 离线程序快照:收集程序运行时配置、线程dump。内存dump等信息建立一个快照,并可以将快照发送给开发者进行bug反馈。
  • 插件化处理,有无限扩展可能

VisualVM使用

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值