JVM参数查看以及调优

妖精的绣舞 提交于 2019-12-04 03:59:26

JVM常用命令汇总:

jps:
查看各个应用对应进程ID

Jmap:
查看内存信息,实例个数以及占用内存大小
jmap -heap 10200(进程ID)
查看堆信息

jmap -dump:format=b,file=dump.hprof 10200(进程ID)
手动转储堆内存信息

jvisualvm:
启动jvisualvm,使用JvisualVM工具查看堆信息

启动jvisualvm

装载dump文件

查看

内存溢出的时候自动打印转存堆栈
‐XX:+PrintGCDetails -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=D:\heapDump.dump 
示例代码:
JVM设置:-Xms10M -Xmx10M -XX:+PrintGCDetails -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=D:\heapDump.dump

import java.util.ArrayList;
import java.util.List;

public class TestAutoDump {

    public static void main(String args[]) {
        List<byte[]> lists = new ArrayList<>();
        while(true) {
            byte[] bytes = new byte[1000*1024];
            lists.add(bytes);
        }
    }

}
// 运行结果如下:
[GC (Allocation Failure) [PSYoungGen: 1734K->488K(2560K)] 1734K->740K(9728K), 0.0007782 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
[GC (Allocation Failure) [PSYoungGen: 1548K->504K(2560K)] 1800K->1780K(9728K), 0.0008307 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
[GC (Allocation Failure) [PSYoungGen: 2541K->488K(2560K)] 3817K->3780K(9728K), 0.0009803 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
[GC (Allocation Failure) [PSYoungGen: 2534K->504K(2560K)] 5826K->5804K(9728K), 0.0006492 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
[Full GC (Ergonomics) [PSYoungGen: 504K->0K(2560K)] [ParOldGen: 5300K->5601K(7168K)] 5804K->5601K(9728K), [Metaspace: 3200K->3200K(1056768K)], 0.0045009 secs] [Times: user=0.16 sys=0.00, real=0.01 secs] 
[Full GC (Ergonomics) [PSYoungGen: 2044K->1000K(2560K)] [ParOldGen: 5601K->6601K(7168K)] 7645K->7601K(9728K), [Metaspace: 3202K->3202K(1056768K)], 0.0047187 secs] [Times: user=0.00 sys=0.00, real=0.01 secs] 
[Full GC (Ergonomics) [PSYoungGen: 2006K->2000K(2560K)] [ParOldGen: 6601K->6597K(7168K)] 8607K->8597K(9728K), [Metaspace: 3209K->3209K(1056768K)], 0.0050641 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
[Full GC (Allocation Failure) [PSYoungGen: 2000K->2000K(2560K)] [ParOldGen: 6597K->6579K(7168K)] 8597K->8579K(9728K), [Metaspace: 3209K->3209K(1056768K)], 0.0049375 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
java.lang.OutOfMemoryError: Java heap space
Dumping heap to D:\heapDump.dump ...
Heap dump file created [9656073 bytes in 0.018 secs]
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
	at TestAutoDump.main(TestAutoDump.java:9)
[Full GC (Ergonomics) [PSYoungGen: 2048K->0K(2560K)] [ParOldGen: 6619K->602K(7168K)] 8667K->602K(9728K), [Metaspace: 3240K->3240K(1056768K)], 0.0045889 secs] [Times: user=0.02 sys=0.02, real=0.02 secs] 
Heap
 PSYoungGen      total 2560K, used 20K [0x00000000ffd00000, 0x0000000100000000, 0x0000000100000000)
  eden space 2048K, 1% used [0x00000000ffd00000,0x00000000ffd05228,0x00000000fff00000)
  from space 512K, 0% used [0x00000000fff80000,0x00000000fff80000,0x0000000100000000)
  to   space 512K, 0% used [0x00000000fff00000,0x00000000fff00000,0x00000000fff80000)
 ParOldGen       total 7168K, used 602K [0x00000000ff600000, 0x00000000ffd00000, 0x00000000ffd00000)
  object space 7168K, 8% used [0x00000000ff600000,0x00000000ff696b30,0x00000000ffd00000)
 Metaspace       used 3246K, capacity 4496K, committed 4864K, reserved 1056768K
  class space    used 353K, capacity 388K, committed 512K, reserved 1048576K

Jstack:
用来查找死锁

// 示例代码如下:
public class DeadLockTest {

    public static void main(String args[]) {

        new Thread(new Runnable() {
            @Override
            public void run() {
                synchronized(A.class) {
                    try {
                        Thread.sleep(5000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    synchronized (B.class) {

                    }
                }

            }
        }).start();

        new Thread(new Runnable() {
            @Override
            public void run() {
                synchronized(B.class) {
                    try {
                        Thread.sleep(5000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    synchronized (A.class) {

                    }
                }
            }
        }).start();

    }

}
class A {}
class B {}

jstack 运行结果日志如下:jstack 14452

2019-11-09 13:08:54
Full thread dump Java HotSpot(TM) 64-Bit Server VM (25.201-b09 mixed mode):

"DestroyJavaVM" #14 prio=5 os_prio=0 tid=0x0000000000f6e800 nid=0x17c8 waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"Thread-1" #13 prio=5 os_prio=0 tid=0x000000001e982800 nid=0x3cd4 waiting for monitor entry [0x000000002062f000]
   java.lang.Thread.State: BLOCKED (on object monitor)
        at DeadLockTest$2.run(DeadLockTest.java:33)
        - waiting to lock <0x000000076b423028> (a java.lang.Class for A)
        - locked <0x000000076b6b2778> (a java.lang.Class for B)
        at java.lang.Thread.run(Thread.java:748)

"Thread-0" #12 prio=5 os_prio=0 tid=0x000000001e971800 nid=0x45bc waiting for monitor entry [0x000000002052f000]
   java.lang.Thread.State: BLOCKED (on object monitor)
        at DeadLockTest$1.run(DeadLockTest.java:16)
        - waiting to lock <0x000000076b6b2778> (a java.lang.Class for B)
        - locked <0x000000076b423028> (a java.lang.Class for A)
        at java.lang.Thread.run(Thread.java:748)
......

若程序是在本地运行,则我们可以使用jvisualvm自动检测死锁
程序运行期间,使用命令jvisualvm打开工具


jstack找出占用CPU最高的堆栈信息
使用命令top -p 14552(java进程ID) 显示java的内存情况
按H,获取每个线程的内存情况,找到占用CPU最高的线程tid
转为十六进制得到 0x1371 ,此为线程id的十六进制表示
执行 jstack 4977|grep -A 10 1371,得到线程堆栈信息中1371这个线程所在行的后面10行
查看对应的堆栈信息找出可能存在问题的代码

Jinfo
查看正在运行的java应用程序的扩展参数

Jstat
jstat命令可以查看堆内存各部分的使用量,以及加载类的数量。
命令的格式如下:jstat [-命令选项] [vmid] [间隔时间(毫秒)] [查询次数]
jstat -gc pid 最常用,可以评估程序内存使用及GC压力整体情况
S0C:第一个幸存区的大小
S1C:第二个幸存区的大小
S0U:第一个幸存区的使用大小
S1U:第二个幸存区的使用大小
EC:伊甸园区的大小
EU:伊甸园区的使用大小
OC:老年代大小
OU:老年代使用大小
MC:方法区大小(元空间)
MU:方法区使用大小
CCSC:压缩类空间大小
CCSU:压缩类空间使用大小
YGC:年轻代垃圾回收次数
YGCT:年轻代垃圾回收消耗时间,单位s
FGC:老年代垃圾回收次数
FGCT:老年代垃圾回收消耗时间,单位
sGCT:垃圾回收消耗总时间,单位s

可以持续观察内存各部分的变化趋势,以及Young GC 和Full GC的频率,判断堆里面各个区域(Eden区域,S0,S1区域,以及Old区域)内存大小的合理性
持续观察命令示例:
jstat -gc 10200 1000 100
观察线程10200的各个区域内存变化,以及GC情况,每一秒中打印一条日志,打印100次


优化思路其实简单来说就是尽量让每次Young GC后的存活对象小于Survivor区域的50%,都留存在年轻代里。尽量别让对象进入老年代。尽量减少Full GC的频率,避免频繁Full GC对JVM性能的影响

内存泄露:
指的是对象已经不再使用,但是还在内存里面占用空间,且垃圾收集机制,无法回收该内存空间


如何分析GC日志:
GC日志的获取:
应用程序配置自动转储GC信息:‐XX:+PrintGCDetails ‐XX:+PrintGCTimeStamps ‐XX:+PrintGCDateStamps ‐Xloggc:./gc.log
GC 日志在线分析工具https://gceasy.io/
分析GC日志免费,查看调优方案收费

分析结果如下图:

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!