乐趣区

关于java:JVM故障诊断和处理工具

本文已被 Github 仓库收录 https://github.com/silently9527/JavaCore
微信公众号:贝塔学 Java

前言

前几天中午正在和共事最近聊股市较好,这几天每天都能够喝点肉汤,心里还是挺快乐的;正在这个时候收到了线上告警邮件和运维同学的音讯,“你们有服务挂了!”,心里一紧,立马关上电脑看来下线上 cat 监控大盘,发现很多服务都在报错,依据 cat 上的监控日志很快发现了其中一个服务内存溢出导致其余调用服务也有问题,居然曾经定位到了出问题的服务,那就简略了,没有是重启解决不了的问题,重启之后很快服务都恢复正常了。几分钟之后又报错了,同样也是这个服务内存溢出,通过排查后发现该服务的堆内存被改小了,好家伙,运维同学不讲武德,搞偷袭,趁我没反馈过去调了内存,内存调整回去之后服务就复原了失常。

预先把线上的快照文件拖了下来剖析,发现自身这个我的项目的代码也有些问题,本文就整顿了一下 JVM 罕用的剖析工具。

命令行工具

在装置完 JDK 之后在 JAVA_HOME/bin 目录下 JDK 曾经提供了很多命令行的工具

可能咱们最罕用的就是 javajavac 这两个命令,除了这两个命令之外还有提供很多其余的实用工具,本文次要来一起学习对 JVM 监控诊断工具

虚拟机过程情况工具(jps)

该工具的性能比拟繁多,与 linux 中的 ps 性能相似,用来列出正在运行的虚拟机过程,并显示出运行的主类和过程号

命令格局:jps [option] [hostid]

> 如果须要查看近程机器的 jvm 过程须要填写hostid,并且须要应用 RMI,比方:rmi://192.168.2.128:12345

罕用的选项:

  • -q : 只显示出虚拟机的过程 id(lvmid),省略主类名
  • -m : 输入启动时传递给主类的参数
  • -l : 显示出主类的全名,包含 jar 包门路
  • -v : 输入虚拟机过程启动时的 JVM 参数

虚拟机统计信息监控工具(jstat)

用于监控虚拟机运行状态信息的命令行工具,能够提供内存,垃圾收集等云行时的数据

命令格局:jstat [option vmid] [interval [s|ms] [count]]

interval 示意距离多久工夫查问一次,count 示意查问多少次,比方:每个两秒查问一次过程 52412 的垃圾收集状况,共查问 5 次

jstat -gc 52412 2s 5

罕用的选项:

  • -class: 监控类装载,卸载次数和总空间以及加载类的耗时
  • -gc: 监控 java 堆的状况
  • -gcutil: 次要输入各个空间应用的百分比
  • -gcnew: 次要是监控新生代的 GC 情况
  • -gcold: 监控老年代的 GC 情况
  • -compiler: 输入 JIT 编译器编译过的办法和耗时信息

查看堆空间的应用百分比: jstat -gcutil 52412 2s 5

java 配置信息工具(jinfo)

能够通过 jinfo 实时的查看和调整虚拟机的各项参数;能够通过 jps -v 查看虚拟机启动时候指定的参数信息,如果须要查看未显示指定的参数默认值也能够通过jinfo -flag

jinfo -flag CMSInitiatingOccupancyFraction 52412

jinfo 除了能够查看参数以外,还能够在运行时批改一些容许被批改的参数

Java 内存映像工具(jmap)

jmap 用于生成 JVM 堆的快照文件,除了应用 jmap 工具,咱们通常也会在配置 JVM 的启动参数 -XX:+HeapDumpOnOutOfMemoryError 让 JVM 在发送内存溢出之后主动生成 dump 文件。

命令格局:jmap [option] vmid

比方生成 java 堆的快照文件

jmap -dump:live,format=b,file=/Users/huaan9527/Desktop/heap.hprof 59950

罕用的选项:

  • -F: 当虚拟机对 -dump 选项没有响应时可用抉择应用这个参数强制生成快照
  • -histo: 显示出堆中对象统计信息。

堆栈跟踪工具(jstack)

用于生成 JVM 以后线程的快照信息。通常用于查问什么起因导致线程长时间的进展,比方:线程死循环,死锁,期待网络 /IO

命令格局:jstack [option] vmid

罕用的选项:

  • -F: 当申请不被响应时强制输入
  • -l: 除了显示堆栈外,还须要显示锁的信息
  • -m: 如果调用到本地办法,显示出 C /C++ 的堆栈

VisualVM 可视化工具

VisualVM 是目前 JDK 自带的性能最强的运行监督和故障处理程序,在 VisualVM 之前,JDK 也提供了一款可视化工具 JConsole,因为 JConsole 的所有性能在 VisualVM 都有,所以可视化工具大家简直都抉择应用 VisualVM。

VisualVM 自身是基于 Netbean 开发的,所以具备了插件扩大性能,装置插件之后下面介绍的所有命令行的工具的性能都能够在 VisualVM 中应用。能够在在 JAVA_HOME/bin 目录下执行 jvisualvm 启动。

  • 插件装置

默认状况 VisualVM 提供的性能很少,须要咱们在菜单栏 -> 工具 -> 插件外面装置插件,我这是全副插件都装置了

性能演示

  • 应用程序、概述、监督

显示出以后本机所有的 JVM 过程,这里显示的内容和后面说的命令行 jps 显示的内容一样

以后虚拟机启动信息的展现,比方:JVM 启动参数、零碎参数

这个页面相当于命令 jstat 的性能,显示出了 CPU, 内存,线程,类装载以后处于什么状况

生成 dump 文件能够在应用程序窗口右键菜单中选择,也能够在这个页面点击右上角的 堆 dump

  • Visual GC

此页次要展现了 GC 相干的信息,这是在性能调优时罕用的页面之一

咱们能够写个程序来观看下这个截图各个内存区域的变动状况,为了让图的成果显著须要批改 JVM 的启动参数

-Xmx100m -Xms100m -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/Users/huaan9527/Desktop
public static void main(String[] args) {List<datatest> datas = new ArrayList&lt;&gt;();

    IntStream.range(0, 10000).forEach(index -&gt; {datas.add(new DataTest());

        try {Thread.sleep(50);
        } catch (InterruptedException e) {e.printStackTrace();
        }
    });

    System.gc();}

static class DataTest {byte[] bytes = new byte[1024];
}

  • 线程

本页的性能相当于命令行工具jstack,次要是用于查看什么起因导致线程长时间期待,咱们写程序来演示下期待内部资源、锁期待、死循环这几种申请

期待内部资源

public static void main(String[] args) throws IOException {BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
    System.out.println(reader.readLine());
    try {Thread.sleep(1000000);
    } catch (InterruptedException e) {e.printStackTrace();
    }
}

选中 main 线程,右侧会看到以后线程运行到了 readBytes,期待键盘输入

当咱们在控制台输出之后再次查看 main 线程的状态,此时进入了 TIME_WAIT 状态

锁期待

public static void main(String[] args) throws IOException, InterruptedException {Thread thread = createLockThread(new Object());
    thread.join();}

public static Thread createLockThread(final Object lock) {Thread lockThread = new Thread(() -&gt; {synchronized (lock) {
            try {lock.wait();
            } catch (InterruptedException e) {e.printStackTrace();
            }
        }
    }, "lockThread");
    lockThread.start();
    return lockThread;
}

lockThread 线程在期待 lock 对象的 notify 办法被调用,此时处于 WAITING 状态,在被唤醒之前是不会再调配执行工夫

死循环

public static void main(String[] args) throws IOException, InterruptedException {while (true) ;
}

线程始终处于运行状态,从堆栈追踪里能够看出代码始终停留在了 191 行,在空循环上用尽调配的执行工夫

总结

本篇介绍了命令行工具和可视化工具,下篇实战演示下如何通过这些工具对 Idea 运行速度调优


写到最初(点关注,不迷路)

文中或者会存在或多或少的有余、谬误之处,有倡议或者意见也十分欢送大家在评论交换。

最初,白嫖不好,创作不易 ,心愿敌人们能够 点赞评论关注 三连,因为这些就是我分享的全副能源起源????

原创不易 转载请注明出处:https://silently9527.cn/archives/100

退出移动版