首页 > 编程语言 > 详细

java虚拟机(十)--性能监控工具实战内存溢出和死锁

时间:2019-07-11 16:42:52      阅读:195      评论:0      收藏:0      [点我收藏+]

  在之前就曾经简单介绍过jdk自带的性能检测工具,但是只是很入门的内容。没有真正的用过都是白扯了,面试的时候也说不过去,更别提真正

在生产环境去解决问题,所以这里我们学习一下真正解决问题的过程,最起码面试的时候不是只能纸上谈兵。

  如果没有了解过java性能监控与故障处理工具,可以参考:java虚拟机(八)--java性能监控与故障处理工具,当然这篇文章也会介绍这些内容

  jvm参数类型:java虚拟机(九)--常用jvm参数

  本文基于jdk1.8

jvm参数类型:

  这部分内容之前也简单介绍过,这里再重新学习下,参数可以以下几种:

标准参数:不同jvm版本几乎不会变化

-help

-server -client

-version -showversion

# java -version
java version "1.8.0_102"
Java(TM) SE Runtime Environment (build 1.8.0_102-b14)
Java HotSpot(TM) 64-Bit Server VM (build 25.102-b14, mixed mode)

-cp -classpath

X参数:非标准化参数,不同jvm版本可能发生变化,但是变化不大

-Xint:解释执行

-Xcomp:第一次使用编译成本地代码

-Xmixed:混合模式,jvm自己决定是否编译成本地代码

[root@iZuf6fkfhthmdm1nwdg5isZ ~]# java -version
java version "1.8.0_102"
Java(TM) SE Runtime Environment (build 1.8.0_102-b14)
Java HotSpot(TM) 64-Bit Server VM (build 25.102-b14, mixed mode)
[root@iZuf6fkfhthmdm1nwdg5isZ ~]# java -Xcomp -version
java version "1.8.0_102"
Java(TM) SE Runtime Environment (build 1.8.0_102-b14)
Java HotSpot(TM) 64-Bit Server VM (build 25.102-b14, compiled mode)
[root@iZuf6fkfhthmdm1nwdg5isZ ~]# java -Xint -version
java version "1.8.0_102"
Java(TM) SE Runtime Environment (build 1.8.0_102-b14)
Java HotSpot(TM) 64-Bit Server VM (build 25.102-b14, interpreted mode)

XX参数:非标准化参数,想对不太稳定,主要用户jvm调优和debug

Boolean类型:

格式:-XX:[+ -]<name>表示启动或者禁用name属性

举个栗子:

  -XX:+UseConcMarkSweepGC,使用cms垃圾处理器

  -XX:+UseG1GC,使用G1垃圾处理器

非Boolean类型:

格式:-XX:<name>=<value>键值对类型,表示name属性值为value

举个栗子:

  -XX:MaxGCPauseMillis=500,表示GC停顿的最大时间为500ms

  -XX:GCTimeRatio=19

-Xmx:就是-XX:InitialHeapSize,初始化堆大小,也就是最小堆内存

-Xms:就是-XX:MaxHeapSize,最大堆内存

所以-Xmx和-Xms不是X类型参数,而是XX类型参数

查看运行时参数:

-XX:+PrintFlagsInitial,打印出参数初始值

-XX:+PrintFlagsFinal,打印出参数最终值

-XX:+UnlockExperimentalVMOptions解锁试验参数

-XX:+UnlockDiagnosticVMOptions解锁诊断参数

-XX:+PrintCommandLineFlags打印命令行参数

举个栗子:

java -XX:+PrintFlagsInitial -version > a.txt

我们上面命令启动的进程把所有的命令初始值都打印到a.txt,打开文件发现700+参数

    uintx MaxGCMinorPauseMillis                     = 18446744073709551615                    {product}
    uintx MaxGCPauseMillis                          = 18446744073709551615                    {product}
    uintx MaxHeapFreeRatio                          = 70                                  {manageable}
    uintx MaxHeapSize                               = 130862280                           {product}
    intx MaxInlineLevel                            = 9                                   {product}
    bool UseG1GC                                   = false                               {product}

这里=指的是默认jvm的参数,而:=为用户自行修改了参数,我这里还没修改过参数

jdk8所有命令参数详解:https://docs.oracle.com/javase/8/docs/technotes/tools/unix/,来自Oracle官网,当然其他版本的文档也都有

jps命令:参看正在运行的Java线程,和Linux的ps差不多

[root@iZuf6fkfhthmdm1nwdg5isZ local]# jps
32464 jar
17593 jar
14234 Jps
[root@iZuf6fkfhthmdm1nwdg5isZ local]# jps -l
32464 user-0.0.1-SNAPSHOT.jar
17593 eureka-0.0.1-SNAPSHOT.jar
14252 sun.tools.jps.Jps

Jinfo命令:查看正在运行的参数,和jps联合使用

查看17593的参数,这里是Spring cloud的eureka组件运行进程号

[root@iZuf6fkfhthmdm1nwdg5isZ local]# jinfo -flag MaxHeapSize 17593  //打印出进程号为17593的MaxHeapSize参数大小
-XX:MaxHeapSize=994050048
[root@iZuf6fkfhthmdm1nwdg5isZ local]# jinfo -flags 17593  //打印出17593的所有非默认参数,而命令行参数这里是为空
Attaching to process ID 17593, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 25.102-b14
Non-default VM flags: -XX:CICompilerCount=2 -XX:InitialHeapSize=62914560 -XX:MaxHeapSize=994050048 -XX:MaxNewSize=331350016 -XX:MinHeapDeltaBytes=524288 -XX:NewSize=20971520 -XX:OldSize=41943040 -XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX:+UseParallelGC 
Command line: 

Jstat:查看jvm统计信息

option:-class,-compiler,-gc等

1、类加载:

# jstat -class 17593 1000 10    //查看该进程的类加载信息,每1000ms打印一次,总打印10次
Loaded  Bytes  Unloaded  Bytes     Time   
 11618 20145.6       74   109.7      10.47
 11618 20145.6       74   109.7      10.47
 11618 20145.6       74   109.7      10.47
 11618 20145.6       74   109.7      10.47
 11618 20145.6       74   109.7      10.47
 11618 20145.6       74   109.7      10.47
 11618 20145.6       74   109.7      10.47
 11618 20145.6       74   109.7      10.47
 11618 20145.6       74   109.7      10.47
 11618 20145.6       74   109.7      10.47

2、垃圾回收:

option:-gc、-gcutil、-gccause、-gcnew、-gcold

# jstat -gc 17593 1000 5
 S0C    S1C    S0U    S1U      EC       EU        OC         OU       MC     MU    CCSC   CCSU   YGC     YGCT    FGC    FGCT     GCT   
1024.0 1024.0  0.0   384.0  29184.0  24461.9   75776.0    26031.3   61784.0 58858.3 8064.0 7502.5    107    0.696   3      0.366    1.062
1024.0 1024.0  0.0   384.0  29184.0  24461.9   75776.0    26031.3   61784.0 58858.3 8064.0 7502.5    107    0.696   3      0.366    1.062
1024.0 1024.0  0.0   384.0  29184.0  24461.9   75776.0    26031.3   61784.0 58858.3 8064.0 7502.5    107    0.696   3      0.366    1.062
1024.0 1024.0  0.0   384.0  29184.0  24461.9   75776.0    26031.3   61784.0 58858.3 8064.0 7502.5    107    0.696   3      0.366    1.062
1024.0 1024.0  0.0   384.0  29184.0  24461.9   75776.0    26031.3   61784.0 58858.3 8064.0 7502.5    107    0.696   3      0.366    1.062
-gc选项

S0C、S1C、S0U、S1U:当前survivor0、survivor1容量(kB)和使用率

EC、EU:当前的eden space容量(kB)和使用率

OC、OU:当前old space容量(kB)和使用率

MC、MU:Metaspace 容量(kB)和使用率

CCSC、CCSU:Compressed class space容量(kB)和使用率

YGC、YGCT:Young GC的次数和时间

FGC、FGCT:Full GC的次数和时间

GCT:GC总时间

C:Capacity就是次数、容量

U:utilization就是使用率、利用率

T:time就是时间

3、JIT编译:

Option:-compiler、-PrintCompilation

# jstat -compiler 17593
Compiled Failed Invalid   Time   FailedType FailedMethod
   11759      1       0    50.01          1 org/springframework/core/annotation/AnnotationUtils findAnnotation

这里我们先实现堆和非堆的内存溢出,然后后面通过工具进行分析原因

堆内存溢出:

@Data
@AllArgsConstructor
public class User {

    private int id;
    private String name;
}
//设置堆大小为-Xms20m -Xmx20m
@GetMapping("/heap")
public String heap() {
    int i = 0;
    while (true) {
        userList.add(new User(i++, UUID.randomUUID().toString()));
    }
}
输出结果:java.lang.OutOfMemoryError: GC overhead limit exceeded

Metaspace内存溢出:

这里需要asm去创建class文件

<dependency>
    <groupId>asm</groupId>
    <artifactId>asm</artifactId>
    <version>3.2</version>
</dependency>
public class Metaspace extends ClassLoader {

    public static List<Class<?>> createClasses() {
        // 类持有
        List<Class<?>> classes = new ArrayList<Class<?>>();
        // 循环1000w次生成1000w个不同的类。
        for (int i = 0; i < 10000000; ++i) {
            ClassWriter cw = new ClassWriter(0);
            // 定义一个类名称为Class{i},它的访问域为public,父类为java.lang.Object,不实现任何接口
            cw.visit(Opcodes.V1_1, Opcodes.ACC_PUBLIC, "Class" + i, null,
                    "java/lang/Object", null);
            // 定义构造函数<init>方法
            MethodVisitor mw = cw.visitMethod(Opcodes.ACC_PUBLIC, "<init>",
                    "()V", null, null);
            // 第一个指令为加载this
            mw.visitVarInsn(Opcodes.ALOAD, 0);
            // 第二个指令为调用父类Object的构造函数
            mw.visitMethodInsn(Opcodes.INVOKESPECIAL, "java/lang/Object",
                    "<init>", "()V");
            // 第三条指令为return
            mw.visitInsn(Opcodes.RETURN);
            mw.visitMaxs(1, 1);
            mw.visitEnd();
            Metaspace test = new Metaspace();
            byte[] code = cw.toByteArray();
            // 定义类
            Class<?> exampleClass = test.defineClass("Class" + i, code, 0, code.length);
            classes.add(exampleClass);
        }
        return classes;
    }
}
//设置非堆metaspace大小为-XX:MetaspaceSize=32M -XX:MaxMetaspaceSize=32M
@GetMapping("/nonheap")
public String nonheap() {
    while (true) {
        classList.addAll(Metaspace.createClasses());
    }
}
输出结果:java.lang.OutOfMemoryError: Metaspace

 

 

 

5

未完待续。。。今天应该能写完

 

 

6

java虚拟机(十)--性能监控工具实战内存溢出和死锁

原文:https://www.cnblogs.com/huigelaile/p/11170814.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!