JVM-04 调优实战

1、Jdk自带的常见命令

一般通过命令行工具查询某个进程的信息,都需要进程号。

[root@VM-0-8-centos ~]# jps
14084 Launcher
14136 Csdn
12172 RemoteMavenServer36
7724 Jps

1.1 java -heap (pid)

查看垃圾收集器信息,初始化堆内存配置,堆空间内存占用情况

C:\Users\Administrator>jmap -heap 14136
Attaching to process ID 14136, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 25.152-b16

using thread-local object allocation.
Parallel GC with 6 thread(s)

Heap Configuration:
   MinHeapFreeRatio         = 0
   MaxHeapFreeRatio         = 100
   MaxHeapSize              = 4282384384 (4084.0MB)
   NewSize                  = 89128960 (85.0MB)
   MaxNewSize               = 1427111936 (1361.0MB)
   OldSize                  = 179306496 (171.0MB)
   NewRatio                 = 2
   SurvivorRatio            = 8
   MetaspaceSize            = 21807104 (20.796875MB)
   CompressedClassSpaceSize = 1073741824 (1024.0MB)
   MaxMetaspaceSize         = 17592186044415 MB
   G1HeapRegionSize         = 0 (0.0MB)

Heap Usage:
PS Young Generation
Eden Space:
   capacity = 67108864 (64.0MB)
   used     = 64722984 (61.724647521972656MB)
   free     = 2385880 (2.2753524780273438MB)
   96.44476175308228% used
From Space:
   capacity = 11010048 (10.5MB)
   used     = 0 (0.0MB)
   free     = 11010048 (10.5MB)
   0.0% used
To Space:
   capacity = 11010048 (10.5MB)
   used     = 0 (0.0MB)
   free     = 11010048 (10.5MB)
   0.0% used
PS Old Generation
   capacity = 179306496 (171.0MB)
   used     = 0 (0.0MB)
   free     = 179306496 (171.0MB)
   0.0% used

7197 interned Strings occupying 679784 bytes.

1.2 jmap(java memory map) 查看内存问题

1.2.1 jmap -histo (pid) >./log.txt

查看进程的内存信息,实例个数及所占空间

C:\Users\Administrator>jmap -histo 14136

 num     #instances         #bytes  class name
----------------------------------------------
   1:         67958       35515848  [B
   2:         95675        6862512  [C
   3:         22976        5717688  [I
   4:         68342        1640208  java.lang.String
   5:         40269        1288608  java.util.HashMap$Node
   6:         24330         973200  java.util.HashMap$KeyIterator
   7:         11248         889968  [Ljava.util.HashMap$Node;
   8:         11974         574752  java.util.HashMap
   9:         12713         568792  [Ljava.lang.Object;
  10:          7151         457664  java.util.regex.Matcher
  11:         11897         409448  [Ljava.lang.String;
  12:         10051         321632  sun.security.util.DerInputBuffer
  13:         11023         264552  sun.security.util.DerInputStream
  14:          7174         229568  sun.security.util.DerValue
  15:          9527         228648  java.util.ArrayList
  16:          9411         225864  sun.security.x509.X509AttributeName
  17:          1843         211448  java.lang.Class
  18:          9530         152480  java.util.HashSet

备注:

  • num :序号
  • instances: 实例数量
  • bytes :占用空间大小
  • class name :类名称([C is a char[],[S is a short[],[I is a int[],[B is a byte[])
1.2.2 jmap -dump:live,format=b,file=jvm.hprof (pid)

生成的jvm.hprof文件,可以下载下来放入jvisualvm.exe文件,来分析生成文件的时刻JVM内存的情况。更好的实践则是在环境中运行时,设置参数. -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=./jvm.dump ,保证内存异常时,生产该文件以便分析异常的原因。
在这里插入图片描述

1.3 jstack 查看虚拟机栈问题

1.3.1 jstack 查找死锁

先找到运行进程的进程号,本机:5516 JstackFountDealLock。下方代码运行,线程0和线程1各自先锁住1个对象,5秒后再去锁另一个对象,此时会造成死锁。

public class JstackFountDealLock {
    private static Object lock1 = new Object();
    private static Object lock2 = new Object();

    public static void main(String[] args) {

        new Thread(()->{
            synchronized (lock1){
                System.out.println("锁对象lock1");
                try {
                    Thread.sleep(5000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                synchronized (lock2){
                    System.out.println("锁对象lock2");
                }
            }
        }).start();

        new Thread(()->{
            synchronized (lock2){
                System.out.println("锁对象lock2");
                try {
                    Thread.sleep(5000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                synchronized (lock1){
                    System.out.println("锁对象lock1");
                }
            }
        }).start();

        System.out.println("main线程结束");
    }
}

查看Jstack 5516 ,省略其中无用信息。Found 1 deadlock.

2021-08-22 22:04:06
Full thread dump Java HotSpot(TM) 64-Bit Server VM (25.152-b16 mixed mode):

"Thread-1" #12 prio=5 os_prio=0 tid=0x000000001f04c800 nid=0x1048 waiting for monitor entry [0x000000001f9ee000]
   java.lang.Thread.State: BLOCKED (on object monitor)
        at com.huawei.jvm.JstackFountDealLock.lambda$main$1(JstackFountDealLock.java:40)
        - waiting to lock <0x000000076b0a3308> (a java.lang.Object)
        - locked <0x000000076b0a3318> (a java.lang.Object)
        at com.huawei.jvm.JstackFountDealLock$$Lambda$2/2074407503.run(Unknown Source)
        at java.lang.Thread.run(Thread.java:748)

"Thread-0" #11 prio=5 os_prio=0 tid=0x000000001f04c000 nid=0x34a8 waiting for monitor entry [0x000000001f8ee000]
   java.lang.Thread.State: BLOCKED (on object monitor)
        at com.huawei.jvm.JstackFountDealLock.lambda$main$0(JstackFountDealLock.java:25)
        - waiting to lock <0x000000076b0a3318> (a java.lang.Object)
        - locked <0x000000076b0a3308> (a java.lang.Object)
        at com.huawei.jvm.JstackFountDealLock$$Lambda$1/558638686.run(Unknown Source)
        at java.lang.Thread.run(Thread.java:748)

Found one Java-level deadlock:
=============================
"Thread-1":
  waiting to lock monitor 0x00000000030fbb88 (object 0x000000076b0a3308, a java.lang.Object),
  which is held by "Thread-0"
"Thread-0":
  waiting to lock monitor 0x00000000030fe418 (object 0x000000076b0a3318, a java.lang.Object),
  which is held by "Thread-1"

Java stack information for the threads listed above:
===================================================
"Thread-1":
        at com.huawei.jvm.JstackFountDealLock.lambda$main$1(JstackFountDealLock.java:40)
        - waiting to lock <0x000000076b0a3308> (a java.lang.Object)
        - locked <0x000000076b0a3318> (a java.lang.Object)
        at com.huawei.jvm.JstackFountDealLock$$Lambda$2/2074407503.run(Unknown Source)
        at java.lang.Thread.run(Thread.java:748)
"Thread-0":
        at com.huawei.jvm.JstackFountDealLock.lambda$main$0(JstackFountDealLock.java:25)
        - waiting to lock <0x000000076b0a3318> (a java.lang.Object)
        - locked <0x000000076b0a3308> (a java.lang.Object)
        at com.huawei.jvm.JstackFountDealLock$$Lambda$1/558638686.run(Unknown Source)
        at java.lang.Thread.run(Thread.java:748)

Found 1 deadlock.

用jvisualvm看也是一样的结果。
在这里插入图片描述

1.3.1 jstack 查看CPU飙升问题

1、准备环境
准备一个无限循环的方法,保持CPU不停运算。

public class Math4Cpu {
    public static final int initData = 666;
    public static User user = new User(); 
    public int compute() { 
        //一个方法对应一块栈帧内存区域 12
        int a = 1; 
        int b = 2;
        int c = (a + b) * 10; 
        return c; 
    }
    public static void main(String[] args) {
        Math4Cpu math = new Math4Cpu();
         while (true){ 
             math.compute(); 
         } 
    } 
}

在linux中运行java的字节码文件

java com.asky.jvm.Math4Cpu

通过top命令 #实时查看系统运行情况,检测CPU、内存、进程等。发现此时PID:24400 的进程CPU占用高达97.3%
在这里插入图片描述
2、检查问题所在

top -p <pid>   #(21508) 查看单进程的恶性西情况

在这里插入图片描述
查看当前进程的详细线程情况
按住shift+h —> H
在这里插入图片描述
拿到CPU占用超高的线程号PID 24401(十进制) —> 转化为十六进制 —> 5f51 (十六进制)
执行jstack查看

jstack 24400|grep -A 10 5f51 #jstack (进程pid) | grep -A 100 pid(java线程号)

从报错中的代码行数,可见端谜。
在这里插入图片描述

1.4 jinfo 查看系统属性

1.4.1 jinfo -flags pid 查看JVM启动命令
[root@VM-0-8-centos /]# jinfo -flags 26611
Attaching to process ID 26611, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 25.302-b08
Non-default VM flags: -XX:CICompilerCount=2 -XX:InitialHeapSize=31457280 -XX:MaxHeapSize=482344960 -XX:MaxNewSize=160759808 -XX:MinHeapDeltaBytes=196608 -XX:NewSize=10485760 -XX:OldSize=20971520 -XX:+UseCompressedClassPointers -XX:+UseCompressedOops 
Command line:  
1.4.2 jinfo -sysprops pid 查看java系统参数

在这里插入图片描述

1.5 Jstat 最常用命令

jstat命令可以查看堆内存各部分的使用量,以及加载类的数量。
命令的格式如下: jstat [-命令选项] [vmid] [间隔时间(毫秒)] [查询次数]
注意:使用的jdk版本是jdk8

1.5.1 Jstat -gc pid 查看垃圾回收情况

1)单次查看gc回收情况

S0C :suvivor0区容量(单位KB)
S0U :suvivor0使用量
EC:Eden区容量
EU:Eden区使用量
OC:老年代容量
OU:老年代使用量
MC:元空间容量
MU:元空间使用量
CCSC:压缩类空间大小
CCUS:压缩类空间使用大小
YGC:Young gc自启动后执行的次数
YGCT:young gc耗费的时间,单位s
FGC:full gc的次数
FGCT:full gc耗费的时间,单位s
GCT:young gc和full gc话费的时间之和,单位s

[root@VM-0-8-centos /]# jstat -gc 26611 
 S0C    S1C    S0U    S1U      EC       EU        OC         OU       MC     MU    CCSC   CCSU   YGC     YGCT    FGC    FGCT     GCT   
1024.0 1024.0  0.0    0.0    8192.0   507.9    20480.0      0.0     4480.0 875.6  384.0   76.6       0    0.000   0      0.000    0.000

2)每个1000毫秒运行1次,累计运行10次

stat -gc pid 1000 10
[root@VM-0-8-centos /]# jstat -gc 30343 1000 10
 S0C    S1C    S0U    S1U      EC       EU        OC         OU       MC     MU    CCSC   CCSU   YGC     YGCT    FGC    FGCT     GCT   
1024.0 1024.0  0.0    0.0    8192.0   507.9    20480.0      0.0     4480.0 875.6  384.0   76.6       0    0.000   0      0.000    0.000
1024.0 1024.0  0.0    0.0    8192.0   507.9    20480.0      0.0     4480.0 875.6  384.0   76.6       0    0.000   0      0.000    0.000
1024.0 1024.0  0.0    0.0    8192.0   507.9    20480.0      0.0     4480.0 875.6  384.0   76.6       0    0.000   0      0.000    0.000
1024.0 1024.0  0.0    0.0    8192.0   507.9    20480.0      0.0     4480.0 875.6  384.0   76.6       0    0.000   0      0.000    0.000
1024.0 1024.0  0.0    0.0    8192.0   507.9    20480.0      0.0     4480.0 875.6  384.0   76.6       0    0.000   0      0.000    0.000
1024.0 1024.0  0.0    0.0    8192.0   507.9    20480.0      0.0     4480.0 875.6  384.0   76.6       0    0.000   0      0.000    0.000
1024.0 1024.0  0.0    0.0    8192.0   507.9    20480.0      0.0     4480.0 875.6  384.0   76.6       0    0.000   0      0.000    0.000
1024.0 1024.0  0.0    0.0    8192.0   507.9    20480.0      0.0     4480.0 875.6  384.0   76.6       0    0.000   0      0.000    0.000
1024.0 1024.0  0.0    0.0    8192.0   507.9    20480.0      0.0     4480.0 875.6  384.0   76.6       0    0.000   0      0.000    0.000
1024.0 1024.0  0.0    0.0    8192.0   507.9    20480.0      0.0     4480.0 875.6  384.0   76.6       0    0.000   0      0.000    0.000

Full GC的频率应该控制在几个小时-几天发生/1次。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

旧梦昂志

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值