java代码 linux 修改文件工具类_JDK命令行工具与可视化工具

jdk/bin目录中提供了很多jdk工具,在查看JVM运行状态以及排查问题时需要结合Linux命令并结合这些工具进行使用,在此记录常用命令行工具以及可视化工具的使用。

f6f51c48b8e650c4dbbcaa38eb81afe3.png

命令行工具

e1ca05605764d8ae9fb52c525f2ca4bb.png
jps:虚拟机进程状态工具

jps:主要用它定位Java进程的PID,示例代码如下

/** jps     -q:显示进程ID     -m:显示进程ID,主类名称,以及传入main方法的参数     -1:显示进程ID,主类全名     -v:显示进程ID,王类名称,以及传入JWM的参数     -V:显示进程ID,主类名称(默认) */public class DEMO01 {    public static void main(String[] args) throws IOException {        System.out.println("jps");        //阻塞        System.in.read();    }}复制代码
e9cd3d2c5af37035aca5292d7fe1318d.png
jstat:虚拟机信息监控工具

jstat:Linux环境上,运行期定位JVM性能问题的首选工具,常用来查看内存变化趋势,GC情况、类加载情况等

使用格式 : jstat [option vmid [interval [s|ms] [count]] ]

  • option 代表我们所要查询的虚拟机细信息。主要包括:类装载,垃圾回收,运行期编译情况
  • vmid 若是运行在本地的虚拟机进程那就是程序运行的pid,若是远程虚拟机,格式应该是 [protocol:][//]lvmid[@hostname[:port]/servername]
  • interval 查询间隔
  • count 查询次数

忽略interval和count参数,那么命令只会执行一次 比如 jstat -gc 2101 500 5 表示每500ms查询一次2101进程的垃圾回收情况,一共执行5次

示例一:

public class DEMO02 {    public static void main(String[] args) throws IOException {        System.out.println("jstat");        System.in.read();    }}复制代码
d01a9f622f23ba11cb4908b569889ce1.png
510d00db12094d6d9702102832096779.png

S0C,S1C是指Survivor0区1区的容量;S0U,S1U是指这两幸存区的使用量;C代表Capacity,U代表Used,上面反应的是各个区的初始容量以及使用情况,GC的次数和时间。

示例二:

import java.io.IOException;public class DEMO03 {    //启动参数设置:-Xms20M -Xmx20M -Xmn10M -xx:+UseserialGC -XX: +PrintGcDetails -verbose:gc    public static void main(String[] args) throws IOException {        final int _1MB = 1024 * 1024;        byte[] b1 = new byte[_1MB];        System.out.println("1...");        System.in.read();        byte[] b2 = new byte[2*_1MB];        System.out.println("2...");        System.in.read();        byte[] b3 = new byte[2*_1MB];        System.out.println("3...");        System.in.read();    }}复制代码

指定DEMO03运行时JVM参数,设置堆区为20M,新生代10M,使用Serial垃圾收集器

a83ab3f65d44bfcf80ab5b8a7afb50f7.png
5db5fc3677a8b6ce4e695295c57deca5.png

可以看到在三次打印中,Eden区发生的变化,发生了一次YoungGC,GC时间是0.015S

7800cf97cf8b2c9549c415d4388383d0.png
jstack:查看Java线程堆栈信息

使用格式: jstack [option] vmid

88e8fae429d10cf33ae1e86d6d32f812.png

示例一:一段死循环ava程序,模拟linux环境下疯狂占用cpu资源

improt java.util.Random;public class demo {    public static void main(String[] args) {        while(true){            System.out.println(new Random().nextInt(77778888));        }    }}复制代码

查看系统状况:用top命令去查各个进程CPU、内存的资源消耗情况,找出最耗资源的进程pid,如图所示,最耗资源的是java进程,pid是2818【需要在后台运行很长时间才会有反应.....】

ed5938f22bdcfbeb08ff66365d2b71e5.png

定位到问题线程:定位到具体的问题线程 ps -mp pid -o THREAD,tid,time 如图所示在java进程中2819的线程最耗资源

a49b72b7965b0470b281843fc5590780.png

查看问题线程的堆栈信息:先将线程id转换为16进制(英文小写格式) printf "%x" 问题线程的id转为16进制英文小写

2db6dd327cb7b31ec8b363d3dcb8f604.png

在使用jstack查看线程的堆栈信息 jstack pid |grep tid -A60

a49b975b2e01e061815c2f0e40db0baf.png

由此便可以查看到是demo.java中的第六行出了问题【此处只是小demo去模拟程序死循环,CPU线上预警出现的可能性很多,常见的还有内存泄露、死锁、频繁GC...需要结合linux命令和java命令和实际情况进行逐步排查】

jinfo:查看/设置虚拟机的参数

jinfo可以查看JVM的参数,并允许在程序运行期间修改JVM的参数,这样JVM就不用重启了。

使用格式: jinfo [option] pid ,可以通过-flag[+|-] name 添加和删除一些参数,或者-flag name =value修改一些参数,但是很多参数是不允许修改的

9b368d6aaf1cb6e2c727c86eff1c9139.png
public class DEMO04 {    public static void main(String[] args) throws IOException {        System.out.println("jinfo");        System.in.read();    }}复制代码
851bcd9f90be2014c1010934eab0f6e8.png
238c5923758560b483c14b6110f2aa2a.png
jmap:生成dump文件

jmap用于生成一份堆存储快照(dump),把Java堆区的使用情况快照一份导出来供我们排查问题。

使用格式 : jmap [option] vmid

35bfc0c64b9bf86acdbcbb77a4b2d6b3.png

示例:

public class DEMO05 {    public static void main(String[] args) throws IOException {        System.out.println("jmap");        System.in.read();    }}复制代码

显示堆区的详细信息 jmap -heap pid

41487db0b2a85fb7ab2c83d86ee0de9b.png

生成堆快照存储文件,format=b生成的是二进制文件, jmap -dump:live,format=b,file=D:jmap.bin pid

dd8ef3f69dce15a3e1b8901c9502180d.png
jhat:虚拟机存储快照分析工具

使用jmap将堆区的快照文件导出后,可以使用jhat进行分析,不过jhat现在使用较少。

使用格式: jhat [-stack ] [-refs ] [-port ] [-baseline ] [-debug ] [-version] [-h|-help]

47fe63a1860a0cc49e64011e02083598.png

示例:

10793e5fd6c802b8b34de3ed568eafd2.png
093cde9717d3609c91c70951b858a8d0.png

可视化工具

jconcle

作用:查看Java应用程序运行时情况,监视垃圾收集器的内存变化趋势,以及监视程序内的线程。

示例一:JConsole演示内存变化
public class DEMO07 {    public static void main(String[] args) throws IOException, InterruptedException {        Thread.sleep(5000);        System.out.println("start....");        test();        System.in.read();    }    public static void test() throws InterruptedException {        final int _128K = 128 * 1024;        List list = new ArrayList<>();        for (int i = 0; i < 10000; i++) {            //耗时操作,令监视器的曲线变化更加明显            Thread.sleep(100);            list.add(new byte[_128K]);        }    }}复制代码

在控制台输入jconsole即可启动JConsole客户端

fe958280e778816fb30cf35ccdb595b7.png

JConsole客户端包括概览、内存、线程、类、VM概要、MBean这大块。

概览:主要运行数据的概览,包括堆内存,线程,类,CPU使用情况四项信息的变化趋势图

c9741b830ec6fe8e906e13bc0ddce73f.png

内存:JDK为1.8,使用的垃圾收集器为ParallerScavenge+Parallel Old,可以监视堆内存以及其中各个区域(Eden区,Survivor区,老年代)的变化趋势,还可以监视非堆(元空间)的内存变化趋势,相当于命令行中的jstat

8c22d928cad8f431ff9e228374201074.png

线程:可以查看当前程序有哪些线程在运行,单机可以查看线程的堆栈信息,相当于命令行工具的jstack,其左下角还有检测死锁的按钮。

044e25e2a414612a52a34988291be0e0.png

类:如图所示,显示了系统以及装载的类数量。在详细信息栏中,还显示了已卸载的类数量。

2a4f9fc04599ea5a4af48ab989715618.png

VM概要:VM摘要:在VM摘要页面,JConsole显示了当前应用程序的运行环境。包括虚拟机类型、版本、堆信息以及虚拟机参数等。相当于命令行工具中的jinfo命令

213d7645fbd0855544d5ffd117380e54.png

示例二:JConcle示例死循环、阻塞等待、死锁现象

import java.io.IOException;import java.util.concurrent.TimeUnit;public class DEMO08 {    public static void main(String[] args) throws IOException {        System.in.read();        System.out.println("开启死循环线程");        whileTureThread();        System.in.read();        System.out.println("开启等待线程");        waitThread();        System.in.read();        System.out.println("开启死锁线程");        deadLock();    }    /**     * 死循环线程     */    private static void whileTureThread() {        new Thread(() -> {            while (true) {            }        }, "whileTrueThread").start();    }    /**     * 等待线程     */    private static void waitThread() {        new Thread(() -> {            synchronized (DEMO08.class) {                try {                    DEMO08.class.wait();                } catch (InterruptedException e) {                    e.printStackTrace();                }            }        },"waitThread").start();    }    /**     * 模拟死锁现象     */    private static void deadLock() {        String A = "A";        String B = "B";        new Thread(() -> {            synchronized (A) {                try {                    //睡2秒                    TimeUnit.SECONDS.sleep(2);                } catch (InterruptedException e) {                    e.printStackTrace();                }                synchronized (B) {                    System.out.println("拿到B锁");                }            }        }, "A").start();        new Thread(() -> {            synchronized (B) {                try {                    //睡2秒                    TimeUnit.SECONDS.sleep(2);                } catch (InterruptedException e) {                    e.printStackTrace();                }                synchronized (A) {                    System.out.println("拿到A锁");                }            }        }, "B").start();    }}复制代码

先在控制台回车开启死循环线程,观察cpu占用率情况,可见CPU占用一直居高不下

8f1bdf0856abf022b89494f22c314fe7.png

在去控制台回车开启等待线程观察线程情况,通过查看堆栈信息可以定位到具体哪一行

90f94b25d3c6faab158ba1ce93ccfab3.png

在去控制台回车开启死锁线程观察线程情况,通过查看堆栈信息可以发现A线程在等待B的锁,B线程在等待A的锁

78f51c1285c3450d5a919dbc86de98c4.png
b73f1842cba92fac88a4bb8b84af312c.png

控制台打印情况如图:

4882786192c79792e6f46f35f7ecc854.png
visualvm

还是使用jconcle中示例二的代码,这次在终端输入jvisualvm即可进入。jvisualvm使用方式与jconsole有些相似。先开启死循环观察其cpu使用情况,可以看到也是高居不下,且比较稳定。

3c85cf8e6955e46b6270298c39a9da42.png

查看等待线程:黄色代表的是等待线程,点击线程Dump,即可查看线程的堆栈信息

021a50d735533847091c820ce1cc98a5.png
4a73020d0b31c8f51d0a18b99a3b3eab.png

查看死锁线程,当开启死锁线程后,visualvm可以立即检测到,点击线程Dump,生成快照文件去查看堆栈详情。

881e58fb2786cc62e79f42898eb1f8c6.png
b3a2a86dd9a62010eadb02c525370ba4.png
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值