# JVM学习

参照《深入理解Java虚拟机》一书,对Java虚拟机进行学习。

# JVM运行时数据区域

JVM运行时数据区域有堆内存区,虚拟机栈,本地方法栈,程序计数器,为元空间以及直接内存。如下图:

    1)程序计数器
    程序计数器是一块较小的内存空间,它可以看作是当前线程所执行的字节码的行号指示器(当前线程栈区当前栈帧的执行位置,也就是当前线程执行到了方法的字节码的哪一行)。在Java虚拟机的概念模型里,字节码解释器工作时就是通过改变这个计数器的值来选取下一条需要执行的字节码指令,它是程序控制流的指示器,分支、循环、跳转、异常处理、线程恢复等基础功能都需要依赖这个计数器来完成。
    程序计数器占用内存非常小,小到可以忽略不计。此外,这块内存区域也是唯一一个在《Java虚拟机规范》中没有规定任何OutOfMemoryError情况的区域。
    2)虚拟机栈
    虚拟机栈描述的是Java方法执行的线程内存模型:每一个方法被调用直至执行完毕的过程,就对应着一个栈帧在虚拟机栈中从入栈到出栈的过程。该区域是线程私有的,一般会分配1M左右的内存空间。
    3)本地方法栈
    本地方法栈时当前线程执行本地方法(native方法)的一个栈区(一般分配1M左右的内存),原则上和虚拟机栈没有任何差异,区别仅在于这部分特殊方法仅能通过c++/c实现。因此这部分方法要单独用一个栈区存储。
    4)元空间
    元空间即元数据(包括类的结构信息、方法信息、字段信息、注解信息等)存储的空间,此外元空间中还包含了运行时常量池。
    5)直接内存
    直接内存指的是直接通过操作系统获取的内存。在Java中,只有在NIO相关操作中JVM才会直接通过操作系统获取内存。在64位的操作系统中,直接内存的默认大小通常为1GB。可以通过-XX:MaxDirectMemorySize参数来设置JVM直接内存的最大大小。如果没有显式指定该参数,默认值将是JVM的最大可用内存大小(即-Xmx参数指定的值)。
    6)堆内存区

    堆内存区由新生代及老年代组成,其中新生代区又分为Eden区以及Survived区(2个,对应S0区以及S1区,也即From区以及To区)。
    堆区存储的是对象本身,即一个很特殊的数据结构。可以根据这个数据结构+类的源码构建出一个对象。

# 什么是OOM(OutOfMemory)?

OOM全称“Out Of Memory”,表示内存耗尽。当JVM因为没有足够的内存来为对象分配空间,并且垃圾回收器也已经没有空间可回收时,就会抛出这个错误。需要注意的是,堆区,栈区,本地内存(元空间,直接内存)这几个区域都有可能发生OOM。

# 堆区内存溢出OOM

这里以《深入理解Java虚拟机》第三版2.4节代码清单2-3为例进行说明。
要通过代码模拟堆区的OOM异常,我们只需要一直创建对象就可以了,创建的对象最初会存储在新生代,在多次YoungGC后这部分没有被清理的对象会被存储到老年代,最终新生代,老年代都会被填满,然后在FullGC的时候,内存回收率小于2%,触发OOM。
编写如下代码进行验证。

查看代码
package com.howl.jvm;

import java.util.ArrayList;
import java.util.List;
public class HeapOOM {
    static class OOMObject{
    }
    public static void main(String[] args) {
        List<OOMObject> list = new ArrayList<>();
        while (true) {
            list.add(new OOMObject());
        }
    }
}

设置JVM启动相关参数,如图所示。

执行代码,查看运行结果,可以看到日志中的报错以及生成的hprof文件如图。


接下来我们通过JProfiler工具分析报错的hprof文件。
首先查看Thread Dump,我们可以很明显的看到,此时jvm中的线程并不多,也可以看到有问题的是main线程,它触发了OOM。
接下来查看Current Object Set,我们可以看到此时系统里创建了82W的对象,其中81W是OOMObject,结合Thread Dump,我们很容易就能联想到main线程里创建OOMObject的相关代码可能有问题(对应的就是while循环的代码)。

# 栈区内存溢出OOM

这里栈区包括虚拟机栈和本地方法栈,两者没有太多本质区别。

这里我们通过增大方法栈中的本地变量表长度的方式,编写如下代码进行验证。

查看代码
package com.howl.jvm;

public class JavaVMStackSOF {
    private static int stackLength = 0;
    public static void test() {
        long unused1, unused2, unused3, unused4, unused5,
                unused6, unused7, unused8, unused9, unused10,
                unused11, unused12, unused13, unused14, unused15,
                unused16, unused17, unused18, unused19, unused20,
                unused21, unused22, unused23, unused24, unused25,
                unused26, unused27, unused28, unused29, unused30,
                unused31, unused32, unused33, unused34, unused35,
                unused36, unused37, unused38, unused39, unused40,
                unused41, unused42, unused43, unused44, unused45,
                unused46, unused47, unused48, unused49, unused50,
                unused51, unused52, unused53, unused54, unused55,
                unused56, unused57, unused58, unused59, unused60,
                unused61, unused62, unused63, unused64, unused65,
                unused66, unused67, unused68, unused69, unused70,
                unused71, unused72, unused73, unused74, unused75,
                unused76, unused77, unused78, unused79, unused80,
                unused81, unused82, unused83, unused84, unused85,
                unused86, unused87, unused88, unused89, unused90,
                unused91, unused92, unused93, unused94, unused95,
                unused96, unused97, unused98, unused99, unused100;
        stackLength ++;
        test();
        unused1 = unused2 = unused3 = unused4 = unused5 =
                unused6 = unused7 = unused8 = unused9 = unused10 =
                        unused11 = unused12 = unused13 = unused14 = unused15 =
                                unused16 = unused17 = unused18 = unused19 = unused20 =
                                        unused21 = unused22 = unused23 = unused24 = unused25 =
                                                unused26 = unused27 = unused28 = unused29 = unused30 =
                                                        unused31 = unused32 = unused33 = unused34 = unused35 =
                                                                unused36 = unused37 = unused38 = unused39 = unused40 =
                                                                        unused41 = unused42 = unused43 = unused44 = unused45 =
                                                                                unused46 = unused47 = unused48 = unused49 = unused50 =
                                                                                        unused51 = unused52 = unused53 = unused54 = unused55 =
                                                                                                unused56 = unused57 = unused58 = unused59 = unused60 =
                                                                                                        unused61 = unused62 = unused63 = unused64 = unused65 =
                                                                                                                unused66 = unused67 = unused68 = unused69 = unused70 =
                                                                                                                        unused71 = unused72 = unused73 = unused74 = unused75 =
                                                                                                                                unused76 = unused77 = unused78 = unused79 = unused80 =
                                                                                                                                        unused81 = unused82 = unused83 = unused84 = unused85 =
                                                                                                                                                unused86 = unused87 = unused88 = unused89 = unused90 =
                                                                                                                                                        unused91 = unused92 = unused93 = unused94 = unused95 =
                                                                                                                                                                unused96 = unused97 = unused98 = unused99 = unused100 = 0;
    }
    public static void main(String[] args) {
        try {
            test();
        }catch (Error e){
            System.out.println("stack length:" + stackLength);
            throw e;
        }
    }
}

执行代码,查看运行结果,可以看到控制台的报错信息如下。

# 本地内存溢出OOM

# 元空间溢出OOM

方法区中存放的是类的数据结构,只要不断往方法区中加入新的类,就会产生方法区的溢出,可以使用类加载器不断加载类或者动态代理不断生成类来演示。
这里使用的是JDK8,方法区的具体实现为元空间,也就是说下面的代码演示的是元空间的溢出。

查看代码
package com.howl.jvm;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.List;

/**
 * 演示元空间OOM
 * VM args:-XX:MetaspaceSize=16m -XX:MaxMetaspaceSize=16m
 */
public class MetaSpaceOOM {

    public static void main(String[] args) {

        List<ClassLoader> classLoaderList = new ArrayList<>();
        while (true) {
            ClassLoader loader = new URLClassLoader(new URL[]{});
            Facade t = (Facade) Proxy.newProxyInstance(loader, new Class<?>[]{Facade.class}, new MetaspaceFacadeInvocationHandler(new FacadeImpl()));
            classLoaderList.add(loader);
        }
    }

    public interface Facade {
    }

    public static class FacadeImpl implements Facade {
    }

    public static class MetaspaceFacadeInvocationHandler implements InvocationHandler, com.howl.jvm.MetaspaceFacadeInvocationHandler {
        private Object impl;

        public MetaspaceFacadeInvocationHandler(Object impl) {
            this.impl = impl;
        }

        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            return method.invoke(impl, args);
        }
    }
}

可以很明显的看到报错提示如下图。

# 直接内存溢出OOM

直接内存溢出的唯一条件是直接或间接使用了NIO。直接内存导致OOM时,仅会在日志中看到Exception in thread "main" java.lang.OutOfMemoryError,除此之外再无其他提示。

查看代码
/**
 * 代码来自《深入理解Java虚拟机》一书,这里并未进行验证
 */
package com.howl.jvm;
/**
 * VM Args:-Xmx20M -XX:MaxDirectMemorySize=10M
 * @author zzm
 */
public class DirectMemoryOOM {
    private static final int _1MB = 1024 * 1024;
    public static void main(String[] args) throws Exception {
        Field unsafeField = Unsafe.class.getDeclaredFields()[0];
        unsafeField.setAccessible(true);
        Unsafe unsafe = (Unsafe) unsafeField.get(null);
        while (true) {
            unsafe.allocateMemory(_1MB);
        }
    }
}

# 线程创建过多导致OOM

在java里创建一个新线程时,会为这个线程分配栈区内存空间,默认1M,所以创建线程的动作本身也是会消耗内存的(栈空间的内存应该是直接用的本地内存)。如果线程创建过多,操作系统内存不足,一样会触发OOM。
这里我们在while循环中一直创建线程的方式来模拟,编写如下代码进行验证。

查看代码
package com.howl.jvm;

/**
 * VM Args:-Xss2M
 * 代码没办法验证,windows下直接操作系统假死也没有报错
 * 在32位windows操作系统下会报异常
 * Exception in thread "main" java.lang.OutOfMemoryError: unable to create native thread
 */
public class JavaVMStackOOM {
    // 线程一直在工作
    private void dontStop() {
        while (true) {
        }
    }
    public void stackLeakByThread() {
        // 一直创建线程
        while (true) {
            Thread thread = new Thread(this::dontStop);
            thread.start();
        }
    }
    public static void main(String[] args) throws Throwable {
        JavaVMStackOOM oom = new JavaVMStackOOM();
        oom.stackLeakByThread();
    }
}

# JVM启动参数设置

# 初始内存分配

# 设置堆内存大小 推荐

堆内存大小可以通过-Xms(最小堆内存,默认值是物理内存的1/64)参数和-Xmx(最大堆内存,默认是物理内存的1/4)参数进行设置,一般我们会将这两个参数设置成一样的大小(可以避免垃圾回收后JVM重新分配内存),设置为物理内存的75%的大小。

堆内存里其他分区的设置

1.可以通过-Xmn设置新生代的大小,新生代大小占堆内存的3/8(JDK官方建议)。
2.新生代又分为Eden以及Survivor(两个),一般Eden区占新生代的80%,两个Survivor各占10%(新生代2个Survivor区和Eden区的比值,默认值为8;即Eden区:From区:To区 = 8: 1:1),可以通过-XX:SurvivorRatio参数来调整这个大小,一般不调整。
3.可以通过NewRatio设置新生代(Eden + 2*Survivor)与老年代(不包括永久区)的比值,JDK8的默认值为2(可以看到这个值与-Xmn冲突,一般-Xmn优先级更高)。

# 设置栈内存大小

默认的栈内存大小为1024k(1M),不建议修改(通过-Xss参数可以设置每个线程对应的栈内存的大小)。

# 设置元空间内存大小 推荐

元空间内存大小可以通过-XX:MetaspaceSize以及-XX:MaxMetaspaceSize两个参数进行设置。一般会将这两个参数设置成相同的值。(实际项目里会设置为128m或者512m)

详细说明

使用Java 8以后,关于元空间的JVM参数有两个:-XX:MetaspaceSize=N和 -XX:MaxMetaspaceSize=N,对于64位JVM来说,元空间的默认初始大小是20.75MB,默认的元空间的最大值是无限。MaxMetaspaceSize用于设置metaspace区域的最大值,这个值可以通过mxbean中的MemoryPoolBean获取到,如果这个参数没有设置,那么就是通过mxbean拿到的最大值是-1,表示无穷大。
由于调整元空间的大小需要Full GC,这是非常昂贵的操作,如果应用在启动的时候发生大量Full GC,通常都是由于永久代或元空间发生了大小调整,基于这种情况,一般建议在JVM参数中将MetaspaceSize和MaxMetaspaceSize设置成一样的值,并设置得比初始值要大。

# 设置直接内存大小

直接内存(DirectMemory)的容量大小可通过-XX:MaxDirectMemorySize参数来指定,如果不去指定,则默认与Java堆最大值(由-Xmx指定)一致(实际上直接内存的默认值大小为Eden+(From+To)/2+Old)。

# GC相关参数设置

# 设置GC并发线程数

GC并发线程数可以通过JVM启动参数:-XX:ParallelGCThreads来指定。一般来说,在无特殊要求下,ParallelGCThreads参数使用默认值就可以了。在未明确指定的情况下,JVM会根据逻辑核数ncpus,采用以下公式来计算默认值:
    1) 当ncpus小于8时,ParallelGCThreads = ncpus
    2) 否则 ParallelGCThreads = 8 + (ncpus - 8 ) ( 5/8 )

# 指定垃圾回收器

可以通过参数指定垃圾回收器的使用,一般有如下参数可供选择:
    1)-XX:+UseSerialGC
    对新生代使用Serial算法进行垃圾回收,对老年代使用Serial Old算法进行垃圾回收。
使用串行回收器进行回收,这个参数会使新生代和老年代都使用串行回收器,新生代使用复制算法,老年代使用标记-整理算法。Serial收集器是最基本、历史最悠久的收集器,它是一个单线程收集器。一旦回收器开始运行时,整个系统都要停止。Client模式下默认开启,其他模式默认关闭。
    2) -XX:+UseParNewGC
    对新生代使用ParNew算法进行垃圾回收,对老年代使用Serial Old算法进行垃圾回收。
ParNew收集器是Serial收集器的多线程版本,使用这个参数后会在新生代进行并行回收,老年代仍旧使用串行回收。新生代S区任然使用复制算法。操作系统是多核CPU上效果明显,单核CPU建议使用串行回收器。打印GC详情时ParNew标识着使用了ParNewGC回收器。默认关闭。
    3) -XX:+UseConcMarkSweepGC
    对新生代使用ParNew算法进行垃圾回收,对老年代使用CMS算法进行垃圾回收。
    4)-XX:+UseParallelGC jdk8默认垃圾回收器
    对新生代使用Parallel Scavenge算法进行垃圾回收,对老年代使用Parallel Old算法进行垃圾回收。
代表新生代使用Parallel收集器,老年代使用串行收集器(UseSerialGC)。Parallel Scavenge收集器在各个方面都很类似ParNew收集器,它的目的是达到一个可以控制的吞吐量。吞吐量为CPU用于运行用户代码的时间与CPU总消耗时间的比值,即吞吐量=运行用户代码时间/(运行用户代码时间+垃圾收集时间),虚拟机运行100分钟,垃圾收集花费1分钟,那吞吐量就99%。Server模式默认开启,其他模式默认关闭。
    5) -XX:+UseG1GC jdk9及以上默认垃圾回收器
    G1 GC,全称Garbage-First Garbage Collector,通过-XX:+UseG1GC参数来启用。G1收集器是工作在堆内不同分区上的收集器,分区既可以是年轻代也可以是老年代,同一个代的分区不需要连续。并且每个代分区的数量是可以动态调整的。为老年代设置分区的目的是老年代里有的分区垃圾多,有的分区垃圾少,这样在回收的时候可以专注于收集垃圾多的分区,这也是G1名称的由来。不过这个算法并不适合新生代垃圾收集,因为新生代的垃圾收集算法是复制算法,但是新生代也使用了分区机制主要是因为便于代大小的调整。

# GC日志记录

GC日志记录相关参数可以在触发Young GC以及Full GC的时候打印相关参数,一般情况下不会设置这部分参数(仅在需要分析GC问题时考虑添加参数,GC问题处理后需要移除)。

详细的GC日志参数
# 必选
# 打印基本 GC 信息
-XX:+PrintGCDetails
-XX:+PrintGCDateStamps
# 打印对象分布
-XX:+PrintTenuringDistribution
# 打印堆数据
-XX:+PrintHeapAtGC
# 打印Reference处理信息
# 强引用/弱引用/软引用/虚引用/finalize 相关的方法
-XX:+PrintReferenceGC
# 打印STW时间
-XX:+PrintGCApplicationStoppedTime

# 可选
# 打印safepoint信息,进入 STW 阶段之前,需要要找到一个合适的 safepoint
-XX:+PrintSafepointStatistics
-XX:PrintSafepointStatisticsCount=1

# GC日志输出的文件路径
-Xloggc:/path/to/gc-%t.log
# 开启日志文件分割
-XX:+UseGCLogFileRotation
# 最多分割几个文件,超过之后从头文件开始写
-XX:NumberOfGCLogFiles=14
# 每个文件上限大小,超过就触发分割
-XX:GCLogFileSize=50M

# OOM相关参数设置 重要

与OOM有关的JVM启动参数有3个,分别是HeapDumpOnOutOfMemoryError(在OOM时生成heapdump堆转储文件),HeapDumpPath(堆转储文件的生成路径),OnOutOfMemoryError(发生OOM时的后续动作,一般情况下可以触发一个脚本自动重启服务)。

# 在触发OOM时生成堆转储文件
-XX:+HeapDumpOnOutOfMemoryError
# 堆转储文件的生成路径
-XX:HeapDumpPath=/logs/my_java_service.hprof
-- 一般会写一个脚本重启服务
# 在触发OOM后执行脚本启动服务(一般不会启动OnOutOfMemoryError)
-XX:OnOutOfMemoryError=/script/restart_my_service.sh

# 其他参数设置

# 大对象直接进入老年代

可以通过-XX:PretenureSizeThreshold参数,指定大于该设置值的对象(一般设置1M)直接在老年代分配,这样做的目的就是避免在Eden区及两个Survivor区之间来回复制,产生大量的内存复制操作。

# 长期存活的对象将进入老年代

可以通过参数-XX:MaxTenuringThreshold设置对象晋升老年代的年龄阈值。(对象通常在Eden区里诞生,如果经过第一次Minor GC后仍然存活,并且能被Survivor容纳的话,该对象会被移动到Survivor空间中,并且将其对象年龄设为1岁。对象在Survivor区中每熬过一次Minor GC,年龄就增加1岁,当它的年龄增加到一定程度(默认为15),就会被晋升到老年代中。)

# 完整示例

查看完整实例
java 
# 堆内存分配
## 在指定了-Xmn的情况下-XX:SurvivorRatio这个参数是一个无效参数,可以直接去掉
## -XX:PretenureSizeThreshold=1M 超过1M的对象直接分配到老年代中
-Xms3g -Xmx3g -Xmn2048M -XX:SurvivorRatio=8 -XX:PretenureSizeThreshold=1M
# 元空间内存分配
-XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=128m 
# OOM堆转储配置
-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/logs/dump.log 
# 垃圾回收器设置
## -XX:+UseParNewGC (新生代用ParNew,老年代用Serial Old)
## -XX:+UseConcMarkSweepGC (新生代用ParNew,老年代用CMS)
## 上面两个参数有矛盾,应该只有UseConcMarkSweepGC生效
## -XX:MaxTenuringThreshold 设置新生代转老年代的最大年龄,默认15,这里改成了10
## -XX:CMSInitiatingOccupancyFraction 在使用了CMS垃圾收集器的情况下,老年代内存区超过92%的使用率就会触发FullGC,这里92%的设置同样意义不是太大
## CMS使用的回收算法-“标记-清除”算法会导致收集结束时会有大量空间碎片产生,当然通过参数XX:+UseCMSCompactAtFullCollection可以让jvm在执行完标记清除后再做整理
## -XX:CMSFullGCsBeforeCompaction 配置经过几次的FullGC进行空间碎片整理,空间碎片整理会导致STW
-XX:+UseParNewGC -XX:+UseConcMarkSweepGC -XX:MaxTenuringThreshold=10 -XX:CMSInitiatingOccupancyFraction=92 -XX:+UseCMSCompactAtFullCollection  -XX:CMSFullGCsBeforeCompaction=3
# SecureRandom在java各种组件中使用广泛,可以可靠的产生随机数。但在大量产生随机数的场景下,性能会较低。这时可以使用"-Djava.security.egd=file:/dev/./urandom"加快随机数产生过程 (ps:这个项目是大数据部门用的,确实有产生大量随机数的需求,因此设置了这个参数)
-Djava.security.egd=file:/dev/./urandom 
# 指定要启动的jar包,这里修改了实际项目的包名!
-jar /app/test-app.jar
java 
# -Xmx5120M 5g最大堆内存
-Xmx5120M 
# -Xms5120M 初始堆内存,和最大堆内存设置一致就好
-Xms5120M 
# -Xmn3072M 年轻代 3G
-Xmn3072M 
# 栈内存大小
-Xss1M 
# 当OOM时打印堆内存日志
-XX:+HeapDumpOnOutOfMemoryError
# 对应HeapDumpOnOutOfMemoryError指令的日志路径
-XX:HeapDumpPath=/logs/dump.log
# 本地内存-元空间,最小256M,最大1G,这里还有个隐藏的条件,直接内存,直接内存没设置参数,所以与-Xmn一致,是3072M
-XX:MetaspaceSize=256M -XX:MaxMetaspaceSize=1024M 
-XX:SurvivorRatio=8 
-XX:MaxTenuringThreshold=10 
-XX:PretenureSizeThreshold=3M 
-XX:+UseParNewGC 
-XX:+UseConcMarkSweepGC 
-XX:CMSInitiatingOccupancyFraction=85 
-XX:+UseCMSCompactAtFullCollection 
-XX:CMSFullGCsBeforeCompaction=3 
-jar /umc-test-boot.jar 

# Java前期编译优化以及后期编译优化


# 前期编译优化

前期编译优化指的是将.java文件转换成.class文件的过程,这个过程一般使用javac程序来完成,这个阶段jdk做的优化其实并不多,主要是解析语法糖,将语法糖转换成对应的语法。

# 后期编译优化

后期编译优化指的是在虚拟机以解释器执行方法时,会对方法进行执行次数的统计,如果某方法执行到一定次数,就会被判定为热点方法,热点方法会编译成机器码,后续该方法不走解释器执行,而是直接通过机器码执行。与之相对的如果一个方法长期未执行,它的机器码就会被移除(转换为通过解释器执行)。

# 类加载

类加载指的是把类的.class文件加载到内存中,为后续对象创建提供支持。

# 类加载的时机?

类加载的动作是由线程执行过程中完成的,类在以下四种情况下会加载,分别是虚拟机启动过程初始化入口方法对应的类,直接使用类,反射,父类初始化。
    1)加载入口方法类
    启动java进程服务的时候,虚拟机线程会找到一个入口类,入口类对应有入口方法(main方法),虚拟机线程会对这个特殊类做类加载,然后才能被使用。
    2)直接使用类
    当我们在main线程或它的子线程中,通过new关键字实例化对象,调用类的static方法,修改/读取static属性时,会判断类是否加载,如果没有加载,类会完成它的加载过程。
    3)反射
    通过反射调用的过程中,会判断类是否完成初始化(读取常量),如果没有初始化,类会完成它的加载过程。
    4)初始化父类
    如果一个子类初始化过程中,会首先初始化它的父类,这个时候父类就会间接完成它的加载。

# 类加载的过程都做了什么?

类加载过程中会做三件事,分别是获取类的二进制流,有效性校验,初始化。

    1)获取二进制流
    加载过程第一步,我们要先读取到类的class文件的二进制流,这里有如下几种获取途径,分别是从zip包获取,从网络中获取,从动态代理中获取(自动生成)。
    2)有效性校验
    获取到二进制流之后,就要校验二进制流是否有效了,会校验文件格式,元数据,字节码,符号引用等信息。
    3)初始化
    将类的方法代码,变量名,方法名,返回值等存储到方法区。执行类里的static{}静态代码块代码,生成类的class对象,该对象会被存储到堆内存中。同时在常量池中增加类的符号引用信息,代表类初始化完成。

# 类加载器

类加载器负责加载类对象。

# 类加载器的双亲委派机制


双亲委派机制指的是如果要加载一个类,会优先使用“父类”加载器加载,如父类加载器找不到相应类,子类才会加载该类。

# 破坏双亲委派机制

双亲委派模型不是一个具有强制性约束的模型,而是Java设计者推荐给开发者们的类加载器实现方式。在Java的世界中大部分的类加载器都遵循这个模型,但也有例外的情况,双亲委派模型主要出现过3次较大规模“被破坏”的情况。
    1)jdk1.2前的代码
    2)jdk自己提供的JNDI等服务。
    3)OSGi实现模块化热部署。

# 对象创建

        当前线程在执行方法(方法对应栈区中的栈帧)的时候,如果碰到了new关键字,就会首先开始类加载以及类初始化(默认类未加载),然后会创建对象(对象会存储在堆区中的新生代),对象包含了对象头(对象的锁标志,配合监视器锁就构成了所谓的管程,这也是synchronized同步关键字的原理。此外对象头里还存了对象的分代年龄,这也是垃圾回收的一个重要知识点)以及实例数据。
        此时如果做了线程间的切换,就会把当前执行的字节码的行号记录到程序计数器中(这里假定线程继续执行)。如果这个时候执行了新创建对象的方法,就会把新对象的方法压入到当前线程的栈区。此时,如果执行的方法操作了新对象的实例属性,就会在当前线程的工作内存中创建该属性的副本。

# Java内存与线程模型


    1) 主内存
    Java内存模型规定所有的变量都存储在主内存中(可以理解成主内存是堆内存,但是其实二者没必然联系)。
    2) 工作内存
    每一个线程都对应一个工作内存,线程的工作内存中保存了该线程使用的变量的主内存副本。线程对变量的读写操作都必须在工作内存中进行,线程不能直接读写主内存中的数据。不同线程之间也无法直接访问对方工作内存中的数据。(可以理解工作内存是栈区内存,其实二者也没必然联系)

# 内存间交互操作

内存间交互操作有8个,这8个操作都是原子操作,分别是lock,unlock,read,load,use,assgin,store,write,分别在执行不同的字节码指令的时候触发,如虚拟机遇到一个需要使用变量值的字节码的时候,就会调用use操作。同理,在执行同步开始指令monitorenter的时候会调用lock操作:
    1)lock
    作用于主内存的变量,它把一个变量标识为线程独占的状态。
    2)unlock
    作用于主内存的变量,它把一个变量从线程独占状态释放。
    3)read
    作用于主内存的变量,将变量从主内存拷贝到工作内存,便于load操作执行。
    4)load
    作用于工作内存的变量,把read操作的值放到工作内存的变量副本中。
    5)use
    使用工作内存中的变量。
    6)assign
    赋值。
    7)store
    存储。
    8)write
    把store操作的变量写入工作内存中。

# 特殊操作-volatile关键字的含义?

经过volatile关键字修饰的属性的读写直接经过主内存,不使用工作内存。volatile的变量并不是线程安全的。

# 线程安全

# 线程安全的定义

当多个线程同时访问一个对象时,如果不用考虑这些线程在运行时环境下的调度和交替执行,也不需要做额外的同步,或者在调度方进行任何其他协调操作,调用这个对象的行为都可以获取到正确的结果(读写对象的属性),那么就称这个对象是线程安全的。

# Java中的线程安全

Java中,主要有以下几类线程安全的对象,分别是不可变对象,线程对立对象,绝对线程安全对象,先对线程安全对象,线程兼容对象。

    1) 不可变对象 常见
    不可变对象一定是线程安全的,对于基本类型变量我们只需要声明为final即可,对于引用类型变量,除了变量本身要声明为final,变量中的其他变量同样要声明为final。
    2) 线程对立对象
    线程对立指的是不管调用方是否使用了同步策略,都无法在多线程环境下并发使用。一般不需要考虑线程对立的情况。
    3) 绝对线程安全对象
    绝对线程安全是不管运行是环境如何,调用者都不需要任何额外的同步措施。通常需要付出很大的甚至不切实际的代价才能创建出这样的对象。在java中,我们可以认为这种对象不存在
    4) 相对线程安全对象 常见
    就是通常意义的线程安全,确保这个对象单独的操作是操作安全的。Java语言中,大部分声称线程安全的类都属于这种类型,如:Vector、Hashtable等(类的所有属性,方法都使用了synchronized或者锁等机制保证了线程安全)。
    5) 线程兼容对象 常见
    线程兼容指的是对象本身不是线程安全的(如一个对象的属性未经synchronized修饰,这种对象在java中占比最多),但是可以通过调用方正确的使用同步来保证它是线程安全的。

# 线程安全的实现方式?

有三种方式可以实现线程安全,分别是互斥同步,非阻塞同步,无同步方案。

# 互斥同步

synchronized和reentrantLock都可以实现互斥同步。同时reentrantLock多了一些高级特性,如等待可中断,公平锁,锁可以同时绑定多个条件。

# 非阻塞同步

通过CAS(Compare And Swap比较并交换,操作系统提供的一个原子操作)来实现非阻塞同步,相较互斥同步性能要好一些。

# 无同步方案

可重复代码以及**线程本地存储ThreadLocal(用的较多)**可以实现无同步方案。

# JVM针对synchronized同步锁做了哪些优化?

# 锁消除

锁消除的判断依据基于逃逸分析的数据支持,如果判断到一段代码中,在堆上的所有数据都不会逃逸出去被其他线程访问到,那就可以把他们当做栈上数据对待,认为它们是线程私有的,同步加锁自然也无需进行了。这个时候就可以直接把锁给“消除”掉了。

# 锁粗化

如果虚拟机探测到有这样一串零碎的操作都对同一个对象加锁,将会把加锁同步的范围扩大(粗化)到整个操作序列的外部,这个过程就叫锁粗化。

# 自旋锁

如果两个线程同时请求锁对象,那么第一个线程就可以获取到锁对象,第二个线程会被挂起(后续线程调度策略会重新将这个挂起的线程恢复),对于Java虚拟机来说,线程的挂起与恢复本身就是重量级操作,对性能有影响,因此,我们考虑不挂起线程,而是让没有获取锁对象的线程执行一个忙等待(自旋),自旋结束后再尝试获取锁对象,这个过程就称为自旋锁(个人理解是不是叫“线程自旋”会好一些)。

# 轻量级锁

传统的互斥锁是基于操作系统提供的互斥量特性来实现的,所以称为重量级锁。在无竞争的情况下,轻量级锁使用CAS操作修改对象头中的标志位(如果两个以上线程修改标志位,标志位就会变成2,此时轻量级锁会膨胀为重量级锁)来实现锁的获取和释放,避免了线程的阻塞和唤醒,从而提高了并发性能。

# 偏向锁

偏向锁的目的是消除数据在无竞争条件下的同步原语,进一步提高程序的运行性能。如果说轻量级锁是在无竞争条件下使用CAS操作替代线程的挂起与恢复,那偏向锁就是在无竞争的情况下把整个同步操作都消除掉,连CAS操作都不用去做了。(与轻量级锁一样,偏向锁也是通过修改对象头的标志位来实现的,同样的,如果有2个以上线程同时操作1个对象,偏向锁会立刻失效)。

# 垃圾回收

# 如何判断对象是否存活

有两类算法可以判断对象是否存活,分别是引用计数算法以及可达性分析算法。

# 引用计数算法

在jvm中,没有一款虚拟机的垃圾回收使用引用计数算法,因为该算法会产生循环引用问题,且该问题无法处理。

# 可达性分析算法

可达性分析算法的基本思路就是通过一系列称为“GC Roots”的根对象作为起始节点集,从这些节点开始,根据引用关系向下搜索,搜索过程所走过的路径称为“引用链”(Reference Chain),如果某个对象到GC Roots间没有任何引用链相连,或者用图论的话来说就是从GC Roots到这个对象不可达时,则证明此对象是不可能再被使用的。

# 分代收集理论

当前商业虚拟机的垃圾收集器,大多数都遵循了“分代收集”(Generational Collection)的理论进行设计,分代收集名为理论,实质是一套符合大多数程序运行实际情况的经验法则,它建立在两个分代假说之上:
    1)弱分代假说(Weak Generational Hypothesis):绝大多数对象都是朝生夕灭的。
    2)强分代假说(Strong Generational Hypothesis):熬过越多次垃圾收集过程的对象就越难以消亡。
根据分代收集理论,我们将对象分别存放在新生代以及老年代中。

# 垃圾回收算法

所有垃圾回收算法的实现都基于可达性分析算法

# 标记-清除算法

    最基础的垃圾收集算法是“标记-清除”(Mark-Sweep)算法。如它的名字一样,算法分为“标记”和“清除”两个阶段:首先标记出所有需要回收的对象,在标记完成后,统一回收掉所有被标记的对象,也可以反过来,标记存活的对象,统一回收所有未被标记的对象。标记过程就是对象是否属于垃圾的判定过程(通过可达性分析算法判定)。
    下面提到的标记-复制以及标记-整理算法都是基于标记-清扫算法进行改进。标记之后啥也不做就直接清理掉,就是标记清除算法。显然,这个算法有很大的改进空间,而且执行效率低。在新生代中,我们可以用标记-复制算法进行改进。而在老年代中,我们可以用标记-整理算法进行改进。

# 标记-复制算法 新生代使用

    标记-复制算法常被简称为复制算法。为了解决标记-清除算法面对大量可回收对象时执行效率低的问题,1969年Fenichel提出了一种称为“半区复制”(Semispace Copying)的垃圾收集算法,它将可用内存按容量划分为大小相等的两块,每次只使用其中的一块。当这一块的内存用完了,就将还存活着的对象复制到另外一块上面,然后再把已使用过的内存空间一次清理掉。

# 标记-整理算法 老年代使用

    标记-复制算法在对象存活率较高时就要进行较多的复制操作,效率将会降低。更关键的是,如果不想浪费50%的空间,就需要有额外的空间进行分配担保,以应对被使用的内存中所有对象都100%存活的极端情况,所以在老年代一般不能直接选用这种算法
    针对老年代对象的存亡特征,1974年Edward Lueders提出了另外一种有针对性的“标记-整理”(Mark-Compact)算法,其中的标记过程仍然与“标记-清除”算法一样,但后续步骤不是直接对可回收对象进行清理,而是让所有存活的对象都向内存空间一端移动,然后直接清理掉边界以外的内存。

# 垃圾回收器-新生代

# Serial收集器

Serial是最早也是最简单的新生代垃圾回收器(使用标记-复制算法实现)。Serial垃圾回收器在工作的时候会触发STW(Stop The World),唯一的一个GC线程会在Safepoint安全点暂停所有用户线程,然后进行gc垃圾回收。

# ParNew收集器

ParNew收集器实质上是Serial收集器的多线程并行版本,除了同时使用多条线程进行垃圾收集之外,其余的行为包括Serial收集器可用的所有控制参数(例如:-XX:SurvivorRatio、-XX:PretenureSizeThreshold、-XX:HandlePromotionFailure等)、收集算法、Stop The World、对象分配规则、回收策略等都与Serial收集器完全一致,在实现上这两种收集器也共用了相当多的代码。

# Parallel Scavenge收集器 jdk8默认新生代收集器

    Parallel Scavenge同样是基于标记-复制算法实现的多线程并发的新生代收集器(也叫做自适应吞吐量优先收集器)。与其他收集器不同(CMS等收集器的关注点是尽可能地缩短垃圾收集时用户线程的停顿时间),Parallel Scavenge收集器的目标则是达到一个可控制的吞吐量(吞吐量=(运行用户代码时间)/(运行用户代码时间+运行垃圾收集时间))。
    如果虚拟机完成某个任务,用户代码加上垃圾收集总共耗费了100分钟,其中垃圾收集花掉1分钟,那吞吐量就是99%。停顿时间越短就越适合需要与用户交互或需要保证服务响应质量的程序,良好的响应速度能提升用户体验;而高吞吐量则可以最高效率地利用处理器资源,尽快完成程序的运算任务,主要适合在后台运算而不需要太多交互的分析任务。

自适应吞吐量优先收集器

    jdk8中默认使用Parallel Scavenge收集器,且默认使用-XX:+UseAdaptiveSizePolicy做垃圾收集的自适应的调节策略(虚拟机会根据当前系统的运行情况收集性能监控信息,动态调整新生代的大小(-Xmn)、Eden与Survivor区的比例(-XX:SurvivorRatio)、晋升老年代对象大小(-XX:PretenureSizeThreshold)等细节参数以提供最合适的停顿时间或者最大的吞吐量。),因此,在jdk8中,我们只需要把基本的内存数据设置好(如-Xmx设置最大堆),然后使用-XX:MaxGCPauseMillis参数(更关注最大停顿时间)或-XX:GCTimeRatio(更关注吞吐量)参数给虚拟机设立一个优化目标即可。
    -XX:MaxGCPauseMillis参数允许的值是一个大于0的毫秒数,收集器将尽力保证内存回收花费的时间不超过用户设定值。
    -XX:GCTimeRatio参数的值是一个大于0小于100的整数,也就是垃圾收集时间占总时间的比率,相当于吞吐量的倒数。譬如把此参数设置为19,那允许的最大垃圾收集时间就占总时间的5%(即1/(1+19)),默认值为99,即允许最大1%(即1/(1+99))的垃圾收集时间。

# 垃圾回收器-老年代

# Serial Old收集器

    Serial Old是最早也是最简单的老年代垃圾回收器(使用标记-整理算法实现)。Serial Old垃圾回收器在工作的时候会触发STW(Stop The World),唯一的一个GC线程会在Safepoint安全点暂停所有用户线程,然后进行gc垃圾回收。

# Parallel Old收集器 jdk8默认老年代收集器

    Parallel Old是Parallel Scavenge收集器的老年代版本,支持多线程并发收集,基于标记-整理算法实现。在注重吞吐量或者处理器资源较为稀缺的场合,都可以优先考虑Parallel Scavenge加Parallel Old收集器这个组合(jdk8中Parallel Scavenge以及Parallel Old是默认的新生代以及老年代收集器)。

# CMS收集器

    CMS(Concurrent Mark Sweep并发标记清除)收集器是一种以获取最短回收停顿时间为目标的收集器。CMS收集器是基于标记-清除算法实现的,它的运作过程分为四个步骤,包括:
    1)初始标记(CMS initial mark)
    2)并发标记(CMS concurrent mark)
    3)重新标记(CMS remark)
    4)并发清除(CMS concurrent sweep)
    其中初始标记、重新标记这两个步骤仍然需要“Stop The World”。初始标记仅仅只是标记一下GCRoots能直接关联到的对象,速度很快;并发标记阶段就是从GC Roots的直接关联对象开始遍历整个对象图的过程,这个过程耗时较长但是不需要停顿用户线程,可以与垃圾收集线程一起并发运行;而重新标记阶段则是为了修正并发标记期间,因用户程序继续运作而导致标记产生变动的那一部分对象的标记记录(详见3.4.6节中关于增量更新的讲解),这个阶段的停顿时间通常会比初始标记阶段稍长一些,但也远比并发标记阶段的时间短;最后是并发清除阶段,清理删除掉标记阶段判断的已经死亡的对象,由于不需要移动存活对象,所以这个阶段也是可以与用户线程同时并发的。由于在整个过程中耗时最长的并发标记和并发清除阶段中,垃圾收集器线程都可以与用户线程一起工作,所以从总体上来说,CMS收集器的内存回收过程是与用户线程一起并发执行的。

    CMS是一款优秀的收集器,它最主要的优点在名字上已经体现出来:并发收集、低停顿,一些官方公开文档里面也称之为“并发低停顿收集器”(Concurrent Low Pause Collector)。CMS收集器是HotSpot虚拟机追求低停顿的第一次成功尝试,但是它还远达不到完美的程度,而且缺点很多,CMS只是老年代的垃圾回收器,它还需要和一个新生代垃圾回收器配合使用,然而CMS并不支持与Parallel Scavenge一起使用。因此,只能搭配使用ParNew收集器,且同时CMS还会触发了Concurrent Mode Failure,这时还需要使用Serial Old收集器。基于以上原因,不推荐使用CMS收集器作为老年代收集器。

# G1垃圾回收器 jdk9及以上默认垃圾收集器

    Garbage First(简称G1)也被称为“全功能的垃圾收集器”。它不再使用固定的区域作为新生代,老年代,而是将堆区划分为一个一个小的分区Region(通过-XX:G1HeapRegionSize设定大小,取值范围为1MB~32MB) 。每一个Region可以扮演新生代的Eden空间、Survivor空间,或者老年代空间,如果一个对象的容量超过Region的一半,它就会被定义为“大对象”(如果对象比Region都大,则会使用多个Region存储)。
    G1收集器可以跟踪各个Region里面的垃圾堆积的“价值”大小,价值即回收所获得的空间大小以及回收所需时间的经验值,然后在后台维护一个优先级列表,每次根据用户设定允许的收集停顿时间(使用参数-XX:MaxGCPauseMillis指定,默认值是200毫秒),优先处理回收价值收益最大的那些Region,这也就是“Garbage First”名字的由来。
    G1收集器的运作过程大致可划分为以下四个步骤:
    1)初始标记(Initial Marking):仅仅只是标记一下GC Roots能直接关联到的对象,并且修改TAMS 指针的值,让下一阶段用户线程并发运行时,能正确地在可用的Region中分配新对象。这个阶段需要 停顿线程,但耗时很短,而且是借用进行Minor GC的时候同步完成的,所以G1收集器在这个阶段实际 并没有额外的停顿。
    2)并发标记(Concurrent Marking):从GC Root开始对堆中对象进行可达性分析,递归扫描整个堆 里的对象图,找出要回收的对象,这阶段耗时较长,但可与用户程序并发执行。当对象图扫描完成以 后,还要重新处理SATB记录下的在并发时有引用变动的对象。
    3)最终标记(Final Marking):对用户线程做另一个短暂的暂停,用于处理并发阶段结束后仍遗留 下来的最后那少量的SATB记录。
    4)筛选回收(Live Data Counting and Evacuation):负责更新Region的统计数据,对各个Region的回 收价值和成本进行排序,根据用户所期望的停顿时间来制定回收计划,可以自由选择任意多个Region 构成回收集,然后把决定回收的那一部分Region的存活对象复制到空的Region中,再清理掉整个旧 Region的全部空间。这里的操作涉及存活对象的移动,是必须暂停用户线程,由多条收集器线程并行 完成的。

    从上述阶段的描述可以看出,G1收集器除了并发标记外,其余阶段也是要完全暂停用户线程的, 换言之,它并非纯粹地追求低延迟,官方给它设定的目标是在延迟可控的情况下获得尽可能高的吞吐 量,所以才能担当起“全功能收集器”的重任与期望。

# 虚拟机性能监控及故障处理

# 基础故障处理工具

有以下基础故障分析工具可以使用,分别是jps(获取java进程号,后续其他指令如jstat,jinfo,jmap,jstack均依赖jps获取到的jvm进程号),jinfo(查询以及修改配置信息),jstat(监控GC),jmap(生成堆转储heapdump文件),jhat(分析heapdump文件),jstack(生成线程快照)。

    1)jps:虚拟机进程状况分析
    jps(JVM Process Status Tool)指令与操作系统中的ps指令一样,都可以用来查看java进程的相关信息。一般从运维的角度来看,我们都是通过ps auxww | grep java 这条指令查找java进程的,其实用jps指令效果会更好。
    jps的实现原理很简单,在进程运行的时候,悄咪咪的在操作系统的临时目录里将相关信息写入,执行jps指令的过程实际上就是读取文件信息的过程。

[root@hkdcl215156 ~]# jps -v
2625 Elasticsearch -Xms1g -Xmx1g -XX:+UseConcMarkSweepGC -XX:CMSInitiatingOccupancyFraction=75 -XX:+UseCMSInitiatingOccupancyOnly -XX:+AlwaysPreTouch -Xss1m -Djava.awt.headless=true -Dfile.encoding=UTF-8 -Djna.nosys=true -XX:-OmitStackTraceInFastThrow -Dio.netty.noUnsafe=true -Dio.netty.noKeySetOptimization=true -Dio.netty.recycler.maxCapacityPerThread=0 -Dlog4j.shutdownHookEnabled=false -Dlog4j2.disable.jmx=true -Djava.io.tmpdir=/tmp/elasticsearch.xLU3InmU -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=data -XX:ErrorFile=logs/hs_err_pid%p.log -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+PrintTenuringDistribution -XX:+PrintGCApplicationStoppedTime -Xloggc:logs/gc.log -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=32 -XX:GCLogFileSize=64m -Des.path.home=/app/elasticsearch-6.5.1 -Des.path.conf=/app/elasticsearch-6.5.1/config -Des.distribution.flavor=default -Des.distribution.type=tar
8979 Bootstrap -Djava.net.preferIPv4Stack=true -Xms512m -Xmx512m -Djava.awt.headless=true -XX:+HeapDumpOnOutOfMemoryError -XX:+DisableExplicitGC -Dfile.encoding=UTF-8 -javaagent:/app/gravitee/graviteeio-full-1.25.1/graviteeio-gateway-1.25.1/boot/jetty-alpn-agent-2.0.9.jar -Dvertx.disableFileCaching=true -Dvertx.disableFileCPResolving=true -Dvertx.disableContextTiming=true -Dvertx.disableWebsockets=true -Dvertx.logger-delegate-factory-class-name=io.vertx.core.logging.SLF4JLogDelegateFactory
3846 Bootstrap -Djava.net.preferIPv4Stack=true -Xms1024m -Xmx1024m -Djava.awt.headless=true -XX:+HeapDumpOnOutOfMemoryError -XX:+DisableExplicitGC -Dfile.encoding=UTF-8
8009 Bootstrap -Djava.net.preferIPv4Stack=true -Xms1024m -Xmx1024m -Djava.awt.headless=true -XX:+HeapDumpOnOutOfMemoryError -XX:+DisableExplicitGC -Dfile.encoding=UTF-8
442796 jar -Xms512m -Xmx512m
10827 Jps -Dapplication.home=/app/lib/jdk1.8.0_92 -Xms8m
4827 Bootstrap -Djava.net.preferIPv4Stack=true -Xms1024m -Xmx2048m -Djava.awt.headless=true -XX:+HeapDumpOnOutOfMemoryError -XX:+DisableExplicitGC -Dfile.encoding=UTF-8 -Dgravitee.home=/app/gravitee/graviteeio-full-1.25.1/graviteeio-management-api-1.25.1 -Dvertx.disableFileCaching=true -Dvertx.disableFileCPResolving=true -Dvertx.logger-delegate-factory-class-name=io.vertx.core.logging.SLF4JLogDelegateFactory

    2)jinfo:Java配置信息查看

# 打印jinfo的帮助文档
[root@hkdcl215156 ~]# jinfo --help
Usage:
    jinfo [option] <pid>
        (to connect to running process 查看某个正在运行的java进程的配置信息)
    jinfo [option] <executable <core>
        (to connect to a core file 查看某个核心文件的配置信息)
    jinfo [option] [server_id@]<remote server IP or hostname>
        (to connect to remote debug server 查看某个开启了debug运行模式的远程服务进程的配置信息)

where <option> is one of:
    # 查看某个属性的值
    -flag <name>         to print the value of the named VM flag
    # 启用/禁用某个属性
    -flag [+|-]<name>    to enable or disable the named VM flag
    # 设置某个属性的值
    -flag <name>=<value> to set the named VM flag to the given value
    # 打印所有能查看的属性信息
    -flags               to print VM flags
    # 打印系统属性
    -sysprops            to print Java system properties
    # 打印所有能打印的信息
    <no option>          to print both of the above
    # 打印帮助文档
    -h | -help           to print this help message
查看详情
# 打印所有能打印的信息
[root@hkdcl215156 ~]# jinfo 8979
Attaching to process ID 8979, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 25.92-b14
Java System Properties:

java.runtime.name = Java(TM) SE Runtime Environment
java.vm.version = 25.92-b14
sun.boot.library.path = /app/lib/jdk1.8.0_92/jre/lib/amd64
java.vendor.url = http://java.oracle.com/
java.vm.vendor = Oracle Corporation
path.separator = :
file.encoding.pkg = sun.io
java.vm.name = Java HotSpot(TM) 64-Bit Server VM
sun.os.patch.level = unknown
sun.java.launcher = SUN_STANDARD
user.country = US
user.dir = /app/gravitee/graviteeio-full-1.25.1/graviteeio-gateway-1.25.1
java.vm.specification.name = Java Virtual Machine Specification
java.runtime.version = 1.8.0_92-b14
java.awt.graphicsenv = sun.awt.X11GraphicsEnvironment
os.arch = amd64
java.endorsed.dirs = /app/lib/jdk1.8.0_92/jre/lib/endorsed
gravitee.home = /app/gravitee/graviteeio-full-1.25.1/graviteeio-gateway-1.25.1
line.separator = 

java.io.tmpdir = /tmp
java.vm.specification.vendor = Oracle Corporation
os.name = Linux
sun.jnu.encoding = UTF-8
java.library.path = /usr/java/packages/lib/amd64:/usr/lib64:/lib64:/lib:/usr/lib
io.netty.noJdkZlibDecoder = false
sun.nio.ch.bugLevel = 
java.class.version = 52.0
java.specification.name = Java Platform API Specification
java.net.preferIPv4Stack = true
vertx.disableFileCPResolving = true
sun.management.compiler = HotSpot 64-Bit Tiered Compilers
os.version = 4.19.90-24.4.v2101.ky10.x86_64
user.home = /root
user.timezone = Asia/Hong_Kong
java.awt.printerjob = sun.print.PSPrinterJob
file.encoding = UTF-8
java.specification.version = 1.8
vertx.disableFileCaching = true
user.name = root
java.class.path = /app/gravitee/graviteeio-full-1.25.1/graviteeio-gateway-1.25.1/lib/gravitee-gateway-standalone-bootstrap-1.25.1.jar:/app/gravitee/graviteeio-full-1.25.1/graviteeio-gateway-1.25.1/boot/jetty-alpn-agent-2.0.9.jar
java.vm.specification.version = 1.8
sun.arch.data.model = 64
sun.java.command = io.gravitee.gateway.standalone.boostrap.Bootstrap
java.home = /app/lib/jdk1.8.0_92/jre
user.language = en
java.specification.vendor = Oracle Corporation
awt.toolkit = sun.awt.X11.XToolkit
java.vm.info = mixed mode
vertx.logger-delegate-factory-class-name = io.vertx.core.logging.SLF4JLogDelegateFactory
java.version = 1.8.0_92
java.ext.dirs = /app/lib/jdk1.8.0_92/jre/lib/ext:/usr/java/packages/lib/ext
sun.boot.class.path = /app/lib/jdk1.8.0_92/jre/lib/resources.jar:/app/lib/jdk1.8.0_92/jre/lib/rt.jar:/app/lib/jdk1.8.0_92/jre/lib/sunrsasign.jar:/app/lib/jdk1.8.0_92/jre/lib/jsse.jar:/app/lib/jdk1.8.0_92/jre/lib/jce.jar:/app/lib/jdk1.8.0_92/jre/lib/charsets.jar:/app/lib/jdk1.8.0_92/jre/lib/jfr.jar:/app/lib/jdk1.8.0_92/jre/classes
java.awt.headless = true
logback.configurationFile = /app/gravitee/graviteeio-full-1.25.1/graviteeio-gateway-1.25.1/config/logback.xml
java.vendor = Oracle Corporation
file.separator = /
java.vendor.url.bug = http://bugreport.sun.com/bugreport/
gravitee.conf = /app/gravitee/graviteeio-full-1.25.1/graviteeio-gateway-1.25.1/config/gravitee.yml
sun.io.unicode.encoding = UnicodeLittle
sun.cpu.endian = little
vertx.disableWebsockets = true
vertx.disableContextTiming = true
sun.cpu.isalist = 

VM Flags:
Non-default VM flags: -XX:CICompilerCount=3 -XX:+DisableExplicitGC -XX:+HeapDumpOnOutOfMemoryError -XX:InitialHeapSize=536870912 -XX:MaxHeapSize=536870912 -XX:MaxNewSize=178782208 -XX:MinHeapDeltaBytes=524288 -XX:NewSize=178782208 -XX:OldSize=358088704 -XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX:+UseParallelGC 
Command line:  -Djava.net.preferIPv4Stack=true -Xms512m -Xmx512m -Djava.awt.headless=true -XX:+HeapDumpOnOutOfMemoryError -XX:+DisableExplicitGC -Dfile.encoding=UTF-8 -javaagent:/app/gravitee/graviteeio-full-1.25.1/graviteeio-gateway-1.25.1/boot/jetty-alpn-agent-2.0.9.jar -Dvertx.disableFileCaching=true -Dvertx.disableFileCPResolving=true -Dvertx.disableContextTiming=true -Dvertx.disableWebsockets=true -Dvertx.logger-delegate-factory-class-name=io.vertx.core.logging.SLF4JLogDelegateFactory
# 打印所有的flags
[root@hkdcl215156 ~]# jinfo -flags 8979
Attaching to process ID 8979, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 25.92-b14
Non-default VM flags: -XX:CICompilerCount=3 -XX:+DisableExplicitGC -XX:+HeapDumpOnOutOfMemoryError -XX:InitialHeapSize=536870912 -XX:MaxHeapSize=536870912 -XX:MaxNewSize=178782208 -XX:MinHeapDeltaBytes=524288 -XX:NewSize=178782208 -XX:OldSize=358088704 -XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX:+UseParallelGC 
Command line:  -Djava.net.preferIPv4Stack=true -Xms512m -Xmx512m -Djava.awt.headless=true -XX:+HeapDumpOnOutOfMemoryError -XX:+DisableExplicitGC -Dfile.encoding=UTF-8 -javaagent:/app/gravitee/graviteeio-full-1.25.1/graviteeio-gateway-1.25.1/boot/jetty-alpn-agent-2.0.9.jar -Dvertx.disableFileCaching=true -Dvertx.disableFileCPResolving=true -Dvertx.disableContextTiming=true -Dvertx.disableWebsockets=true -Dvertx.logger-delegate-factory-class-name=io.vertx.core.logging.SLF4JLogDelegateFactory
# 打印某一个特定key属性的value值
[root@hkdcl215156 ~]# jinfo -flag CMSInitiatingOccupancyFraction 8979
-XX:CMSInitiatingOccupancyFraction=-1

    3)jstat:虚拟机统计信息监视
    jstat主要监视类加载,即时编译,以及GC这三块的内容。它的用法如下:

jstat -option pid 频率 次数

    其中涉及的操作option如下:

选项 说明
-class 监视类加载,卸载数量,总空间以及类加载所消耗的时间。
-compiler 输出即时编译器编译过的方法、耗时等信息。
-printcompilation 输出已经被即时编译的方法。
-gc 监视java堆情况,包括Eden区,2个Survivor区,老年代,元空间的容量,已用空间,垃圾收集时间合计等信息。
-gccapacity 与-gc类似,输出主要关注Java堆各个区域使用到的最大,最小空间。
-gcutil 与-gc类似,输出主要关注已使用空间占总空间的百分比。
-gccause 与-gcutil功能一致,会额外输出导致上一次垃圾收集产生的原因。
-gcnew 监视新生代垃圾收集情况。
-gcnewapacity 与-gcnew类似,输出主要关注Java堆新生代使用到的最大,最小空间。
-gcold 监视老年代垃圾收集情况。
-gcoldapacity 与-gcold类似,输出主要关注Java堆老年代使用到的最大,最小空间。
-gcmetacapacity 输出元空间使用的最大以及最小空间。
# 查看进程的类加载情况,每500ms查询一次,一共查询2次
[root@hkdcl215156 ~]# jstat -class 8979 500 2
Loaded  Bytes  Unloaded  Bytes     Time   
 16489 31194.4        7     6.5      10.65
 16489 31194.4        7     6.5      10.65
# 查看进程的垃圾回收情况,每500ms查询一次,一共查询2次
[root@hkdcl215156 ~]# jstat -gc 8979 500 2
 S0C    S1C    S0U    S1U      EC       EU        OC         OU       MC     MU    CCSC   CCSU   YGC     YGCT    FGC    FGCT     GCT   
512.0  512.0  160.0   0.0   173568.0 159855.2  349696.0   153482.5  163328.0 96514.4 13568.0 11335.5  20022  124.132   4      0.473  124.606
512.0  512.0  160.0   0.0   173568.0 159929.2  349696.0   153482.5  163328.0 96514.4 13568.0 11335.5  20022  124.132   4      0.473  124.606

    4)jmap:Java内存映像工具
    jmap(Memory Map for Java)命令可用于生产堆栈储(heapdump)文件(文件以.hprof结尾),查询finalize执行队列、Java堆和方法区的详细信息,如空间使用率、当前用的是哪种收集器等。jmap的用法如下:

jmap -option pid

    其中涉及的操作option如下:

选项 说明
-dump 生成堆转储快照文件。
-F 当虚拟机进程对-dump指令没有响应的时候可以使用-F选项强制生成heapdump文件。
-heap 显示Java堆详细信息,如使用了哪种收集器,参数配置,分代情况等。
-histo 显示堆中对象统计信息,包括类,实例数量,合计容量。
-permstat 以ClassLoader(类加载器)为统计口径显示永久代内存状况。
-finalizerinfo 显示在F-Queue中等待Finalizer线程执行finalize()方法的对象。
查看详情
# 通过jmap -dump生成堆转储快照,生成的堆转储文件包含两块,一块是堆信息,另外一块是线程堆信息(jstack)。
[root@hkdcl215156 ~]# jmap -dump:format=b,file=/mydump.hprof 8979
Dumping heap to /mydump.hprof ...
Heap dump file created
[root@hkdcl215156 ~]# cd /
[root@hkdcl215156 /]# ll -h | grep *.hprof
# 这里可以看到生成了一个421M的文件,后续可以用jhat命令分析这个文件
-rw-------    1 root    root    421M Feb 22 09:24 mydump.hprof
# 通过jamp -heap打印java堆详细信息
[root@hkdcl215156 ~]# jmap -heap 8979
Attaching to process ID 8979, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 25.92-b14

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

Heap Configuration:
   MinHeapFreeRatio         = 0
   MaxHeapFreeRatio         = 100
   MaxHeapSize              = 536870912 (512.0MB)
   NewSize                  = 178782208 (170.5MB)
   MaxNewSize               = 178782208 (170.5MB)
   OldSize                  = 358088704 (341.5MB)
   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 = 177733632 (169.5MB)
   # 使用容量
   used     = 117778632 (112.32245635986328MB)
   # 剩余容量
   free     = 59955000 (57.17754364013672MB)
   # 使用百分比
   66.26693590552406% used
# S0/S1其中一个
From Space:
   capacity = 524288 (0.5MB)
   used     = 163840 (0.15625MB)
   free     = 360448 (0.34375MB)
   31.25% used
# S0/S1其中一个
To Space:
   capacity = 524288 (0.5MB)
   used     = 0 (0.0MB)
   free     = 524288 (0.5MB)
   0.0% used
# 老年代 2G
PS Old Generation
   capacity = 358088704 (341.5MB)
   used     = 157395456 (150.10400390625MB)
   free     = 200693248 (191.39599609375MB)
   43.954320323938504% used

22492 interned Strings occupying 2149392 bytes.

    5)jhat:虚拟机堆转储快照分析工具
jhat指令可用来分析jmap指令生成的堆转储文件,使用方式是jhat filename,分析完成后,jhat会生成相应的html页面,同时启动一个web服务,服务默认占用7000端口,使用http://localhost:7000/就可以查看相应的分析页面。一般不推荐使用jhat工具去分析,优先使用Memory Analyzer Tool,JProfiler等工具去分析。

    6)jstack:Java栈区跟踪
    jstack(Stack Trace for Java)命令用于生成虚拟机当前时刻的线程快照(一般称为threaddump或者javacore文件)。线程快照就是当前虚拟机内每一条线程正在执行的方法堆栈的集合,生成线程快照的目的通常是定位线程出现长时间停顿的原因,如线程间死锁、死循环、请求外部资源导致的长时间挂起等,都是导致线程长时间停顿的常见原因。线程出现停顿时通过jstack来查看各个线程的调用堆栈,就可以获知没有响应的线程到底在后台做些什么事情,或者等待着什么资源。jstack的用法如下:

jstack -option pid

    其中涉及的操作option如下:

选项 说明
-F 当正常输出的请求不被响应的时候,强制输出线程堆栈。
-l 除堆栈外,额外显示锁的相关信息。
-m 如果调用到本地方法的话,可以额外显示C/C++的堆栈。
查看详情
# 生成线程栈
[root@hkdcl215156 ~]# jstack 8979 > /jstack.log
# 生成线程栈(只输出本地方法栈)
[root@hkdcl215156 /]# jstack -m 8979 > /jstackm.log
# 生成线程栈(额外输出锁相关信息)
[root@hkdcl215156 /]# jstack -l 8979 > /jstackl.log
[root@hkdcl215156 ~]# cd /
[root@hkdcl215156 /]# ll
-rw-r--r--    1 root    root        48113 Feb 22 09:41 jstackl.log
-rw-r--r--    1 root    root        45887 Feb 22 09:47 jstack.log
-rw-r--r--    1 root    root          170 Feb 22 09:41 jstackm.log

# jstack打印信息如下,这里一共有59个线程
2024-02-22 09:47:20
Full thread dump Java HotSpot(TM) 64-Bit Server VM (25.92-b14 mixed mode):

"Attach Listener" #59 daemon prio=9 os_prio=0 tid=0x00007fb114003000 nid=0x605c waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"logback-8" #58 daemon prio=5 os_prio=0 tid=0x00007fb100013000 nid=0xbb085 waiting on condition [0x00007fb0b63f4000]
   java.lang.Thread.State: WAITING (parking)
	at sun.misc.Unsafe.park(Native Method)
	- parking to wait for  <0x00000000e4c8be80> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
	at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)
	at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2039)
	at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:1081)
	at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:809)
	at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1067)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1127)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
	at java.lang.Thread.run(Thread.java:745)

"logback-7" #57 daemon prio=5 os_prio=0 tid=0x00007fb100011800 nid=0xbb084 waiting on condition [0x00007fb0b64f5000]
   java.lang.Thread.State: WAITING (parking)
	at sun.misc.Unsafe.park(Native Method)
	- parking to wait for  <0x00000000e4c8be80> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
	at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)
	at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2039)
	at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:1081)
	at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:809)
	at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1067)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1127)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
	at java.lang.Thread.run(Thread.java:745)

"logback-6" #56 daemon prio=5 os_prio=0 tid=0x00007fb10000f800 nid=0x87c25 waiting on condition [0x00007fb0b85f8000]
   java.lang.Thread.State: WAITING (parking)
	at sun.misc.Unsafe.park(Native Method)
	- parking to wait for  <0x00000000e4c8be80> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
	at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)
	at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2039)
	at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:1081)
	at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:809)
	at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1067)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1127)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
	at java.lang.Thread.run(Thread.java:745)

"logback-5" #55 daemon prio=5 os_prio=0 tid=0x00007fb100009000 nid=0x87c24 waiting on condition [0x00007fb0b86f9000]
   java.lang.Thread.State: WAITING (parking)
	at sun.misc.Unsafe.park(Native Method)
	- parking to wait for  <0x00000000e4c8be80> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
	at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)
	at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2039)
	at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:1081)
	at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:809)
	at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1067)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1127)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
	at java.lang.Thread.run(Thread.java:745)

"logback-4" #54 daemon prio=5 os_prio=0 tid=0x00007fb10000c000 nid=0x50184 waiting on condition [0x00007fb0ba9fc000]
   java.lang.Thread.State: WAITING (parking)
	at sun.misc.Unsafe.park(Native Method)
	- parking to wait for  <0x00000000e4c8be80> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
	at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)
	at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2039)
	at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:1081)
	at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:809)
	at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1067)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1127)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
	at java.lang.Thread.run(Thread.java:745)

"logback-3" #53 daemon prio=5 os_prio=0 tid=0x00007fb10000a800 nid=0x50180 waiting on condition [0x00007fb0baafd000]
   java.lang.Thread.State: WAITING (parking)
	at sun.misc.Unsafe.park(Native Method)
	- parking to wait for  <0x00000000e4c8be80> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
	at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)
	at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2039)
	at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:1081)
	at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:809)
	at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1067)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1127)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
	at java.lang.Thread.run(Thread.java:745)

"logback-2" #52 daemon prio=5 os_prio=0 tid=0x00007fb100007800 nid=0x19f5a waiting on condition [0x00007fb0babfe000]
   java.lang.Thread.State: WAITING (parking)
	at sun.misc.Unsafe.park(Native Method)
	- parking to wait for  <0x00000000e4c8be80> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
	at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)
	at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2039)
	at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:1081)
	at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:809)
	at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1067)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1127)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
	at java.lang.Thread.run(Thread.java:745)

"logback-1" #51 daemon prio=5 os_prio=0 tid=0x00007fb100008000 nid=0x19f58 waiting on condition [0x00007fb1181c7000]
   java.lang.Thread.State: WAITING (parking)
	at sun.misc.Unsafe.park(Native Method)
	- parking to wait for  <0x00000000e4c8be80> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
	at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)
	at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2039)
	at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:1081)
	at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:809)
	at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1067)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1127)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
	at java.lang.Thread.run(Thread.java:745)

"apikeys-refresher-2" #50 prio=5 os_prio=0 tid=0x00007fb0d410b000 nid=0x2359 waiting on condition [0x00007fb119ac8000]
   java.lang.Thread.State: WAITING (parking)
	at sun.misc.Unsafe.park(Native Method)
	- parking to wait for  <0x00000000e11268c0> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
	at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)
	at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2039)
	at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:1088)
	at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:809)
	at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1067)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1127)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
	at java.lang.Thread.run(Thread.java:745)

"subscriptions-refresher-2" #49 prio=5 os_prio=0 tid=0x00007fb0d4102000 nid=0x2358 waiting on condition [0x00007fb119bc9000]
   java.lang.Thread.State: TIMED_WAITING (parking)
	at sun.misc.Unsafe.park(Native Method)
	- parking to wait for  <0x00000000e114e5e0> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
	at java.util.concurrent.locks.LockSupport.parkNanos(LockSupport.java:215)
	at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.awaitNanos(AbstractQueuedSynchronizer.java:2078)
	at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:1093)
	at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:809)
	at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1067)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1127)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
	at java.lang.Thread.run(Thread.java:745)

"subscriptions-refresher-1" #48 prio=5 os_prio=0 tid=0x00007fb0f4005800 nid=0x2357 waiting on condition [0x00007fb119eca000]
   java.lang.Thread.State: WAITING (parking)
	at sun.misc.Unsafe.park(Native Method)
	- parking to wait for  <0x00000000e114e5e0> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
	at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)
	at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2039)
	at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:1088)
	at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:809)
	at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1067)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1127)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
	at java.lang.Thread.run(Thread.java:745)

"apikeys-refresher-1" #47 prio=5 os_prio=0 tid=0x00007fb100002800 nid=0x2356 waiting on condition [0x00007fb119fcb000]
   java.lang.Thread.State: WAITING (parking)
	at sun.misc.Unsafe.park(Native Method)
	- parking to wait for  <0x00000000e11268c0> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
	at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)
	at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2039)
	at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:1088)
	at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:809)
	at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1067)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1127)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
	at java.lang.Thread.run(Thread.java:745)

"apikeys-refresher-0" #46 prio=5 os_prio=0 tid=0x00007fb0d40d6800 nid=0x2355 waiting on condition [0x00007fb11a0cc000]
   java.lang.Thread.State: TIMED_WAITING (parking)
	at sun.misc.Unsafe.park(Native Method)
	- parking to wait for  <0x00000000e11268c0> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
	at java.util.concurrent.locks.LockSupport.parkNanos(LockSupport.java:215)
	at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.awaitNanos(AbstractQueuedSynchronizer.java:2078)
	at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:1093)
	at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:809)
	at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1067)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1127)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
	at java.lang.Thread.run(Thread.java:745)

"subscriptions-refresher-0" #45 prio=5 os_prio=0 tid=0x00007fb0d40d4000 nid=0x2354 waiting on condition [0x00007fb13c10e000]
   java.lang.Thread.State: WAITING (parking)
	at sun.misc.Unsafe.park(Native Method)
	- parking to wait for  <0x00000000e114e5e0> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
	at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)
	at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2039)
	at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:1088)
	at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:809)
	at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1067)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1127)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
	at java.lang.Thread.run(Thread.java:745)

"RxComputationThreadPool-1" #44 daemon prio=5 os_prio=0 tid=0x00007fb0e81d9800 nid=0x2353 waiting on condition [0x00007fb13c213000]
   java.lang.Thread.State: TIMED_WAITING (parking)
	at sun.misc.Unsafe.park(Native Method)
	- parking to wait for  <0x00000000e25c6a38> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
	at java.util.concurrent.locks.LockSupport.parkNanos(LockSupport.java:215)
	at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.awaitNanos(AbstractQueuedSynchronizer.java:2078)
	at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:1093)
	at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:809)
	at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1067)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1127)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
	at java.lang.Thread.run(Thread.java:745)

"RxCachedWorkerPoolEvictor-1" #43 daemon prio=5 os_prio=0 tid=0x00007fb0e8138800 nid=0x2352 waiting on condition [0x00007fb13c314000]
   java.lang.Thread.State: TIMED_WAITING (parking)
	at sun.misc.Unsafe.park(Native Method)
	- parking to wait for  <0x00000000e25b9f80> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
	at java.util.concurrent.locks.LockSupport.parkNanos(LockSupport.java:215)
	at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.awaitNanos(AbstractQueuedSynchronizer.java:2078)
	at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:1093)
	at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:809)
	at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1067)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1127)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
	at java.lang.Thread.run(Thread.java:745)

"RxSchedulerPurge-1" #42 daemon prio=5 os_prio=0 tid=0x00007fb0e8137800 nid=0x2351 waiting on condition [0x00007fb13c415000]
   java.lang.Thread.State: TIMED_WAITING (parking)
	at sun.misc.Unsafe.park(Native Method)
	- parking to wait for  <0x00000000e25c7428> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
	at java.util.concurrent.locks.LockSupport.parkNanos(LockSupport.java:215)
	at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.awaitNanos(AbstractQueuedSynchronizer.java:2078)
	at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:1093)
	at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:809)
	at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1067)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1127)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
	at java.lang.Thread.run(Thread.java:745)

"org.eclipse.jetty.util.RolloverFileOutputStream" #41 daemon prio=5 os_prio=0 tid=0x00007fb0e8002800 nid=0x234c in Object.wait() [0x00007fb13c916000]
   java.lang.Thread.State: TIMED_WAITING (on object monitor)
	at java.lang.Object.wait(Native Method)
	at java.util.TimerThread.mainLoop(Timer.java:552)
	- locked <0x00000000e0cd7538> (a java.util.TaskQueue)
	at java.util.TimerThread.run(Timer.java:505)

"vert.x-worker-thread-0" #40 prio=5 os_prio=0 tid=0x00007fb0ec009000 nid=0x234b waiting on condition [0x00007fb13ca17000]
   java.lang.Thread.State: WAITING (parking)
	at sun.misc.Unsafe.park(Native Method)
	- parking to wait for  <0x00000000e01489b0> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
	at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)
	at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2039)
	at java.util.concurrent.LinkedBlockingQueue.take(LinkedBlockingQueue.java:442)
	at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1067)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1127)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
	at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
	at java.lang.Thread.run(Thread.java:745)

"DestroyJavaVM" #39 prio=5 os_prio=0 tid=0x00007fb15c00b000 nid=0x2315 waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"gateway-monitor" #37 prio=5 os_prio=0 tid=0x00007fb15dda4000 nid=0x234a waiting on condition [0x00007fb13cb18000]
   java.lang.Thread.State: TIMED_WAITING (parking)
	at sun.misc.Unsafe.park(Native Method)
	- parking to wait for  <0x00000000e0e8cf60> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
	at java.util.concurrent.locks.LockSupport.parkNanos(LockSupport.java:215)
	at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.awaitNanos(AbstractQueuedSynchronizer.java:2078)
	at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:1093)
	at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:809)
	at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1067)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1127)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
	at java.lang.Thread.run(Thread.java:745)

"node-monitor" #36 prio=5 os_prio=0 tid=0x00007fb15dd38800 nid=0x2348 waiting on condition [0x00007fb13ce19000]
   java.lang.Thread.State: TIMED_WAITING (parking)
	at sun.misc.Unsafe.park(Native Method)
	- parking to wait for  <0x00000000e0f099c8> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
	at java.util.concurrent.locks.LockSupport.parkNanos(LockSupport.java:215)
	at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.awaitNanos(AbstractQueuedSynchronizer.java:2078)
	at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:1093)
	at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:809)
	at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1067)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1127)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
	at java.lang.Thread.run(Thread.java:745)

"sync-1" #35 prio=5 os_prio=0 tid=0x00007fb15dd2e000 nid=0x2347 waiting on condition [0x00007fb13d1fd000]
   java.lang.Thread.State: TIMED_WAITING (parking)
	at sun.misc.Unsafe.park(Native Method)
	- parking to wait for  <0x00000000e11ec040> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
	at java.util.concurrent.locks.LockSupport.parkNanos(LockSupport.java:215)
	at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.awaitNanos(AbstractQueuedSynchronizer.java:2078)
	at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:1093)
	at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:809)
	at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1067)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1127)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
	at java.lang.Thread.run(Thread.java:745)

"Statistics Thread-__DEFAULT__-1" #33 daemon prio=5 os_prio=0 tid=0x00007fb15da9d800 nid=0x2345 waiting on condition [0x00007fb13d2fe000]
   java.lang.Thread.State: TIMED_WAITING (parking)
	at sun.misc.Unsafe.park(Native Method)
	- parking to wait for  <0x00000000e1016518> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
	at java.util.concurrent.locks.LockSupport.parkNanos(LockSupport.java:215)
	at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.awaitNanos(AbstractQueuedSynchronizer.java:2078)
	at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:1093)
	at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:809)
	at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1067)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1127)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
	at java.lang.Thread.run(Thread.java:745)

"__DEFAULT__" #32 daemon prio=5 os_prio=0 tid=0x00007fb15da93000 nid=0x2344 in Object.wait() [0x00007fb13d6d8000]
   java.lang.Thread.State: WAITING (on object monitor)
	at java.lang.Object.wait(Native Method)
	- waiting on <0x00000000e1075da8> (a java.util.TaskQueue)
	at java.lang.Object.wait(Object.java:502)
	at java.util.TimerThread.mainLoop(Timer.java:526)
	- locked <0x00000000e1075da8> (a java.util.TaskQueue)
	at java.util.TimerThread.run(Timer.java:505)

"Statistics Thread-__DEFAULT__-1" #30 daemon prio=5 os_prio=0 tid=0x00007fb15da45000 nid=0x2342 waiting on condition [0x00007fb13d7d9000]
   java.lang.Thread.State: TIMED_WAITING (parking)
	at sun.misc.Unsafe.park(Native Method)
	- parking to wait for  <0x00000000e0f02a20> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
	at java.util.concurrent.locks.LockSupport.parkNanos(LockSupport.java:215)
	at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.awaitNanos(AbstractQueuedSynchronizer.java:2078)
	at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:1093)
	at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:809)
	at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1067)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1127)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
	at java.lang.Thread.run(Thread.java:745)

"__DEFAULT__" #29 daemon prio=5 os_prio=0 tid=0x00007fb15d876800 nid=0x2341 in Object.wait() [0x00007fb13dbb3000]
   java.lang.Thread.State: WAITING (on object monitor)
	at java.lang.Object.wait(Native Method)
	- waiting on <0x00000000e0f39920> (a java.util.TaskQueue)
	at java.lang.Object.wait(Object.java:502)
	at java.util.TimerThread.mainLoop(Timer.java:526)
	- locked <0x00000000e0f39920> (a java.util.TaskQueue)
	at java.util.TimerThread.run(Timer.java:505)

"Statistics Thread-__DEFAULT__-1" #27 daemon prio=5 os_prio=0 tid=0x00007fb15c416800 nid=0x233f waiting on condition [0x00007fb13dcb4000]
   java.lang.Thread.State: TIMED_WAITING (parking)
	at sun.misc.Unsafe.park(Native Method)
	- parking to wait for  <0x00000000e1188ff0> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
	at java.util.concurrent.locks.LockSupport.parkNanos(LockSupport.java:215)
	at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.awaitNanos(AbstractQueuedSynchronizer.java:2078)
	at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:1093)
	at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:809)
	at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1067)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1127)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
	at java.lang.Thread.run(Thread.java:745)

"__DEFAULT__" #26 daemon prio=5 os_prio=0 tid=0x00007fb15d72f800 nid=0x233e in Object.wait() [0x00007fb13ddb5000]
   java.lang.Thread.State: WAITING (on object monitor)
	at java.lang.Object.wait(Native Method)
	- waiting on <0x00000000e11e6be8> (a java.util.TaskQueue)
	at java.lang.Object.wait(Object.java:502)
	at java.util.TimerThread.mainLoop(Timer.java:526)
	- locked <0x00000000e11e6be8> (a java.util.TaskQueue)
	at java.util.TimerThread.run(Timer.java:505)

"CleanCursors-2-thread-1" #25 daemon prio=5 os_prio=0 tid=0x00007fb15d5df800 nid=0x233c waiting on condition [0x00007fb13e18d000]
   java.lang.Thread.State: TIMED_WAITING (parking)
	at sun.misc.Unsafe.park(Native Method)
	- parking to wait for  <0x00000000e166eb38> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
	at java.util.concurrent.locks.LockSupport.parkNanos(LockSupport.java:215)
	at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.awaitNanos(AbstractQueuedSynchronizer.java:2078)
	at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:1093)
	at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:809)
	at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1067)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1127)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
	at java.lang.Thread.run(Thread.java:745)

"cluster-ClusterId{value='65bc914866cd4b23131a01e2', description='gravitee.io'}-10.6.215.156:27017" #24 daemon prio=5 os_prio=0 tid=0x00007fb15d5e4000 nid=0x233b waiting on condition [0x00007fb13e28e000]
   java.lang.Thread.State: TIMED_WAITING (parking)
	at sun.misc.Unsafe.park(Native Method)
	- parking to wait for  <0x00000000e1675b50> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
	at java.util.concurrent.locks.LockSupport.parkNanos(LockSupport.java:215)
	at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.awaitNanos(AbstractQueuedSynchronizer.java:2078)
	at com.mongodb.internal.connection.DefaultServerMonitor$ServerMonitorRunnable.waitForSignalOrTimeout(DefaultServerMonitor.java:229)
	at com.mongodb.internal.connection.DefaultServerMonitor$ServerMonitorRunnable.waitForNext(DefaultServerMonitor.java:210)
	at com.mongodb.internal.connection.DefaultServerMonitor$ServerMonitorRunnable.run(DefaultServerMonitor.java:157)
	- locked <0x00000000e1675718> (a com.mongodb.internal.connection.DefaultServerMonitor$ServerMonitorRunnable)
	at java.lang.Thread.run(Thread.java:745)

"CleanCursors-1-thread-1" #23 daemon prio=5 os_prio=0 tid=0x00007fb15cffb800 nid=0x2330 waiting on condition [0x00007fb13eda2000]
   java.lang.Thread.State: TIMED_WAITING (parking)
	at sun.misc.Unsafe.park(Native Method)
	- parking to wait for  <0x00000000e0a22870> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
	at java.util.concurrent.locks.LockSupport.parkNanos(LockSupport.java:215)
	at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.awaitNanos(AbstractQueuedSynchronizer.java:2078)
	at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:1093)
	at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:809)
	at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1067)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1127)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
	at java.lang.Thread.run(Thread.java:745)

"cluster-ClusterId{value='65bc914766cd4b23131a01e1', description='gravitee.io'}-10.6.215.156:27017" #22 daemon prio=5 os_prio=0 tid=0x00007fb15cfe9800 nid=0x232f waiting on condition [0x00007fb13eea3000]
   java.lang.Thread.State: TIMED_WAITING (parking)
	at sun.misc.Unsafe.park(Native Method)
	- parking to wait for  <0x00000000e0a36f68> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
	at java.util.concurrent.locks.LockSupport.parkNanos(LockSupport.java:215)
	at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.awaitNanos(AbstractQueuedSynchronizer.java:2078)
	at com.mongodb.internal.connection.DefaultServerMonitor$ServerMonitorRunnable.waitForSignalOrTimeout(DefaultServerMonitor.java:229)
	at com.mongodb.internal.connection.DefaultServerMonitor$ServerMonitorRunnable.waitForNext(DefaultServerMonitor.java:210)
	at com.mongodb.internal.connection.DefaultServerMonitor$ServerMonitorRunnable.run(DefaultServerMonitor.java:157)
	- locked <0x00000000e0a36a70> (a com.mongodb.internal.connection.DefaultServerMonitor$ServerMonitorRunnable)
	at java.lang.Thread.run(Thread.java:745)

"vert.x-acceptor-thread-0" #21 prio=5 os_prio=0 tid=0x00007fb0f00a7800 nid=0x232e runnable [0x00007fb13f3ed000]
   java.lang.Thread.State: RUNNABLE
	at sun.nio.ch.EPollArrayWrapper.epollWait(Native Method)
	at sun.nio.ch.EPollArrayWrapper.poll(EPollArrayWrapper.java:269)
	at sun.nio.ch.EPollSelectorImpl.doSelect(EPollSelectorImpl.java:93)
	at sun.nio.ch.SelectorImpl.lockAndDoSelect(SelectorImpl.java:86)
	- locked <0x00000000e0226c40> (a io.netty.channel.nio.SelectedSelectionKeySet)
	- locked <0x00000000e025eb88> (a java.util.Collections$UnmodifiableSet)
	- locked <0x00000000e025eab0> (a sun.nio.ch.EPollSelectorImpl)
	at sun.nio.ch.SelectorImpl.select(SelectorImpl.java:97)
	at io.netty.channel.nio.SelectedSelectionKeySetSelector.select(SelectedSelectionKeySetSelector.java:62)
	at io.netty.channel.nio.NioEventLoop.select(NioEventLoop.java:753)
	at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:408)
	at io.netty.util.concurrent.SingleThreadEventExecutor$5.run(SingleThreadEventExecutor.java:897)
	at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
	at java.lang.Thread.run(Thread.java:745)

"vert.x-eventloop-thread-7" #20 prio=5 os_prio=0 tid=0x00007fb15d3e8000 nid=0x232d runnable [0x00007fb13f8f7000]
   java.lang.Thread.State: RUNNABLE
	at sun.nio.ch.EPollArrayWrapper.epollWait(Native Method)
	at sun.nio.ch.EPollArrayWrapper.poll(EPollArrayWrapper.java:269)
	at sun.nio.ch.EPollSelectorImpl.doSelect(EPollSelectorImpl.java:93)
	at sun.nio.ch.SelectorImpl.lockAndDoSelect(SelectorImpl.java:86)
	- locked <0x00000000e0222fd8> (a io.netty.channel.nio.SelectedSelectionKeySet)
	- locked <0x00000000e02240d8> (a java.util.Collections$UnmodifiableSet)
	- locked <0x00000000e0224000> (a sun.nio.ch.EPollSelectorImpl)
	at sun.nio.ch.SelectorImpl.select(SelectorImpl.java:97)
	at io.netty.channel.nio.SelectedSelectionKeySetSelector.select(SelectedSelectionKeySetSelector.java:62)
	at io.netty.channel.nio.NioEventLoop.select(NioEventLoop.java:753)
	at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:408)
	at io.netty.util.concurrent.SingleThreadEventExecutor$5.run(SingleThreadEventExecutor.java:897)
	at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
	at java.lang.Thread.run(Thread.java:745)

"vert.x-eventloop-thread-6" #19 prio=5 os_prio=0 tid=0x00007fb15d3e6800 nid=0x232c runnable [0x00007fb13f9f8000]
   java.lang.Thread.State: RUNNABLE
	at sun.nio.ch.EPollArrayWrapper.epollWait(Native Method)
	at sun.nio.ch.EPollArrayWrapper.poll(EPollArrayWrapper.java:269)
	at sun.nio.ch.EPollSelectorImpl.doSelect(EPollSelectorImpl.java:93)
	at sun.nio.ch.SelectorImpl.lockAndDoSelect(SelectorImpl.java:86)
	- locked <0x00000000e014d118> (a io.netty.channel.nio.SelectedSelectionKeySet)
	- locked <0x00000000e01647f8> (a java.util.Collections$UnmodifiableSet)
	- locked <0x00000000e0164710> (a sun.nio.ch.EPollSelectorImpl)
	at sun.nio.ch.SelectorImpl.select(SelectorImpl.java:97)
	at io.netty.channel.nio.SelectedSelectionKeySetSelector.select(SelectedSelectionKeySetSelector.java:62)
	at io.netty.channel.nio.NioEventLoop.select(NioEventLoop.java:753)
	at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:408)
	at io.netty.util.concurrent.SingleThreadEventExecutor$5.run(SingleThreadEventExecutor.java:897)
	at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
	at java.lang.Thread.run(Thread.java:745)

"vert.x-eventloop-thread-5" #18 prio=5 os_prio=0 tid=0x00007fb15d3e4800 nid=0x232b runnable [0x00007fb13faf9000]
   java.lang.Thread.State: RUNNABLE
	at sun.nio.ch.EPollArrayWrapper.epollWait(Native Method)
	at sun.nio.ch.EPollArrayWrapper.poll(EPollArrayWrapper.java:269)
	at sun.nio.ch.EPollSelectorImpl.doSelect(EPollSelectorImpl.java:93)
	at sun.nio.ch.SelectorImpl.lockAndDoSelect(SelectorImpl.java:86)
	- locked <0x00000000e0167050> (a io.netty.channel.nio.SelectedSelectionKeySet)
	- locked <0x00000000e0168150> (a java.util.Collections$UnmodifiableSet)
	- locked <0x00000000e0168078> (a sun.nio.ch.EPollSelectorImpl)
	at sun.nio.ch.SelectorImpl.select(SelectorImpl.java:97)
	at io.netty.channel.nio.SelectedSelectionKeySetSelector.select(SelectedSelectionKeySetSelector.java:62)
	at io.netty.channel.nio.NioEventLoop.select(NioEventLoop.java:753)
	at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:408)
	at io.netty.util.concurrent.SingleThreadEventExecutor$5.run(SingleThreadEventExecutor.java:897)
	at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
	at java.lang.Thread.run(Thread.java:745)

"vert.x-eventloop-thread-4" #17 prio=5 os_prio=0 tid=0x00007fb15d3e2800 nid=0x232a runnable [0x00007fb13fbfa000]
   java.lang.Thread.State: RUNNABLE
	at sun.nio.ch.EPollArrayWrapper.epollWait(Native Method)
	at sun.nio.ch.EPollArrayWrapper.poll(EPollArrayWrapper.java:269)
	at sun.nio.ch.EPollSelectorImpl.doSelect(EPollSelectorImpl.java:93)
	at sun.nio.ch.SelectorImpl.lockAndDoSelect(SelectorImpl.java:86)
	- locked <0x00000000e016a998> (a io.netty.channel.nio.SelectedSelectionKeySet)
	- locked <0x00000000e01a24c8> (a java.util.Collections$UnmodifiableSet)
	- locked <0x00000000e01a23f0> (a sun.nio.ch.EPollSelectorImpl)
	at sun.nio.ch.SelectorImpl.select(SelectorImpl.java:97)
	at io.netty.channel.nio.SelectedSelectionKeySetSelector.select(SelectedSelectionKeySetSelector.java:62)
	at io.netty.channel.nio.NioEventLoop.select(NioEventLoop.java:753)
	at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:408)
	at io.netty.util.concurrent.SingleThreadEventExecutor$5.run(SingleThreadEventExecutor.java:897)
	at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
	at java.lang.Thread.run(Thread.java:745)

"vert.x-eventloop-thread-3" #16 prio=5 os_prio=0 tid=0x00007fb15d3e1000 nid=0x2329 runnable [0x00007fb13fcfb000]
   java.lang.Thread.State: RUNNABLE
	at sun.nio.ch.EPollArrayWrapper.epollWait(Native Method)
	at sun.nio.ch.EPollArrayWrapper.poll(EPollArrayWrapper.java:269)
	at sun.nio.ch.EPollSelectorImpl.doSelect(EPollSelectorImpl.java:93)
	at sun.nio.ch.SelectorImpl.lockAndDoSelect(SelectorImpl.java:86)
	- locked <0x00000000e01a4d10> (a io.netty.channel.nio.SelectedSelectionKeySet)
	- locked <0x00000000e01a5e10> (a java.util.Collections$UnmodifiableSet)
	- locked <0x00000000e01a5d38> (a sun.nio.ch.EPollSelectorImpl)
	at sun.nio.ch.SelectorImpl.select(SelectorImpl.java:97)
	at io.netty.channel.nio.SelectedSelectionKeySetSelector.select(SelectedSelectionKeySetSelector.java:62)
	at io.netty.channel.nio.NioEventLoop.select(NioEventLoop.java:753)
	at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:408)
	at io.netty.util.concurrent.SingleThreadEventExecutor$5.run(SingleThreadEventExecutor.java:897)
	at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
	at java.lang.Thread.run(Thread.java:745)

"vert.x-eventloop-thread-2" #15 prio=5 os_prio=0 tid=0x00007fb15d3df000 nid=0x2328 runnable [0x00007fb13fdfc000]
   java.lang.Thread.State: RUNNABLE
	at sun.nio.ch.EPollArrayWrapper.epollWait(Native Method)
	at sun.nio.ch.EPollArrayWrapper.poll(EPollArrayWrapper.java:269)
	at sun.nio.ch.EPollSelectorImpl.doSelect(EPollSelectorImpl.java:93)
	at sun.nio.ch.SelectorImpl.lockAndDoSelect(SelectorImpl.java:86)
	- locked <0x00000000e01a8658> (a io.netty.channel.nio.SelectedSelectionKeySet)
	- locked <0x00000000e01e15e0> (a java.util.Collections$UnmodifiableSet)
	- locked <0x00000000e01e1508> (a sun.nio.ch.EPollSelectorImpl)
	at sun.nio.ch.SelectorImpl.select(SelectorImpl.java:97)
	at io.netty.channel.nio.SelectedSelectionKeySetSelector.select(SelectedSelectionKeySetSelector.java:62)
	at io.netty.channel.nio.NioEventLoop.select(NioEventLoop.java:753)
	at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:408)
	at io.netty.util.concurrent.SingleThreadEventExecutor$5.run(SingleThreadEventExecutor.java:897)
	at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
	at java.lang.Thread.run(Thread.java:745)

"vert.x-eventloop-thread-1" #14 prio=5 os_prio=0 tid=0x00007fb15d3dd800 nid=0x2327 runnable [0x00007fb13fefd000]
   java.lang.Thread.State: RUNNABLE
	at sun.nio.ch.EPollArrayWrapper.epollWait(Native Method)
	at sun.nio.ch.EPollArrayWrapper.poll(EPollArrayWrapper.java:269)
	at sun.nio.ch.EPollSelectorImpl.doSelect(EPollSelectorImpl.java:93)
	at sun.nio.ch.SelectorImpl.lockAndDoSelect(SelectorImpl.java:86)
	- locked <0x00000000e01e3e28> (a io.netty.channel.nio.SelectedSelectionKeySet)
	- locked <0x00000000e01e4f28> (a java.util.Collections$UnmodifiableSet)
	- locked <0x00000000e01e4e50> (a sun.nio.ch.EPollSelectorImpl)
	at sun.nio.ch.SelectorImpl.select(SelectorImpl.java:97)
	at io.netty.channel.nio.SelectedSelectionKeySetSelector.select(SelectedSelectionKeySetSelector.java:62)
	at io.netty.channel.nio.NioEventLoop.select(NioEventLoop.java:753)
	at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:408)
	at io.netty.util.concurrent.SingleThreadEventExecutor$5.run(SingleThreadEventExecutor.java:897)
	at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
	at java.lang.Thread.run(Thread.java:745)

"vert.x-eventloop-thread-0" #13 prio=5 os_prio=0 tid=0x00007fb15d3dc000 nid=0x2326 runnable [0x00007fb13fffe000]
   java.lang.Thread.State: RUNNABLE
	at sun.nio.ch.EPollArrayWrapper.epollWait(Native Method)
	at sun.nio.ch.EPollArrayWrapper.poll(EPollArrayWrapper.java:269)
	at sun.nio.ch.EPollSelectorImpl.doSelect(EPollSelectorImpl.java:93)
	at sun.nio.ch.SelectorImpl.lockAndDoSelect(SelectorImpl.java:86)
	- locked <0x00000000e01e7758> (a io.netty.channel.nio.SelectedSelectionKeySet)
	- locked <0x00000000e02207a8> (a java.util.Collections$UnmodifiableSet)
	- locked <0x00000000e02206d0> (a sun.nio.ch.EPollSelectorImpl)
	at sun.nio.ch.SelectorImpl.select(SelectorImpl.java:97)
	at io.netty.channel.nio.SelectedSelectionKeySetSelector.select(SelectedSelectionKeySetSelector.java:62)
	at io.netty.channel.nio.NioEventLoop.select(NioEventLoop.java:753)
	at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:408)
	at io.netty.util.concurrent.SingleThreadEventExecutor$5.run(SingleThreadEventExecutor.java:897)
	at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
	at java.lang.Thread.run(Thread.java:745)

"vertx-blocked-thread-checker" #12 daemon prio=5 os_prio=0 tid=0x00007fb15cb9f800 nid=0x2325 in Object.wait() [0x00007fb144b94000]
   java.lang.Thread.State: TIMED_WAITING (on object monitor)
	at java.lang.Object.wait(Native Method)
	at java.util.TimerThread.mainLoop(Timer.java:552)
	- locked <0x00000000e00167d0> (a java.util.TaskQueue)
	at java.util.TimerThread.run(Timer.java:505)

"AsyncAppender-Worker-async-console" #10 daemon prio=5 os_prio=0 tid=0x00007fb15c7da800 nid=0x2324 waiting on condition [0x00007fb145d24000]
   java.lang.Thread.State: WAITING (parking)
	at sun.misc.Unsafe.park(Native Method)
	- parking to wait for  <0x00000000e00169c0> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
	at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)
	at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2039)
	at java.util.concurrent.ArrayBlockingQueue.take(ArrayBlockingQueue.java:403)
	at ch.qos.logback.core.AsyncAppenderBase$Worker.run(AsyncAppenderBase.java:289)

"AsyncAppender-Worker-async-file" #9 daemon prio=5 os_prio=0 tid=0x00007fb15c7d9800 nid=0x2323 waiting on condition [0x00007fb145e25000]
   java.lang.Thread.State: WAITING (parking)
	at sun.misc.Unsafe.park(Native Method)
	- parking to wait for  <0x00000000e0016c00> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
	at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)
	at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2039)
	at java.util.concurrent.ArrayBlockingQueue.take(ArrayBlockingQueue.java:403)
	at ch.qos.logback.core.AsyncAppenderBase$Worker.run(AsyncAppenderBase.java:289)

"Service Thread" #8 daemon prio=9 os_prio=0 tid=0x00007fb15c1eb000 nid=0x2321 runnable [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"C1 CompilerThread2" #7 daemon prio=9 os_prio=0 tid=0x00007fb15c1e7800 nid=0x2320 waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"C2 CompilerThread1" #6 daemon prio=9 os_prio=0 tid=0x00007fb15c1e5000 nid=0x231f waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"C2 CompilerThread0" #5 daemon prio=9 os_prio=0 tid=0x00007fb15c1e4000 nid=0x231e waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"Signal Dispatcher" #4 daemon prio=9 os_prio=0 tid=0x00007fb15c17f000 nid=0x231d runnable [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"Finalizer" #3 daemon prio=8 os_prio=0 tid=0x00007fb15c14c000 nid=0x231c in Object.wait() [0x00007fb1465f4000]
   java.lang.Thread.State: WAITING (on object monitor)
	at java.lang.Object.wait(Native Method)
	at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:143)
	- locked <0x00000000e0022850> (a java.lang.ref.ReferenceQueue$Lock)
	at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:164)
	at java.lang.ref.Finalizer$FinalizerThread.run(Finalizer.java:209)

"Reference Handler" #2 daemon prio=10 os_prio=0 tid=0x00007fb15c147800 nid=0x231b in Object.wait() [0x00007fb1466f5000]
   java.lang.Thread.State: WAITING (on object monitor)
	at java.lang.Object.wait(Native Method)
	at java.lang.Object.wait(Object.java:502)
	at java.lang.ref.Reference.tryHandlePending(Reference.java:191)
	- locked <0x00000000e0022a08> (a java.lang.ref.Reference$Lock)
	at java.lang.ref.Reference$ReferenceHandler.run(Reference.java:153)

"VM Thread" os_prio=0 tid=0x00007fb15c140000 nid=0x231a runnable 

"GC task thread#0 (ParallelGC)" os_prio=0 tid=0x00007fb15c020800 nid=0x2316 runnable 

"GC task thread#1 (ParallelGC)" os_prio=0 tid=0x00007fb15c022800 nid=0x2317 runnable 

"GC task thread#2 (ParallelGC)" os_prio=0 tid=0x00007fb15c024000 nid=0x2318 runnable 

"GC task thread#3 (ParallelGC)" os_prio=0 tid=0x00007fb15c026000 nid=0x2319 runnable 

"VM Periodic Task Thread" os_prio=0 tid=0x00007fb15c1f8000 nid=0x2322 waiting on condition 

JNI global references: 2350

# 其他工具

# JProfiler

JProfiler是heapdump分析工具,使用JProfiler工具打开.hprof文件,可以看到两块内容,分别是Current Object Set(当前堆的所有对象情况)以及Thread Dump(当前堆的线程情况,与jstack指令输出的内容一致)。


# 火焰图:cpu分析工具

通过安装perf软件包,可以使用这个软件,对cpu进行监控,生成监控文件。生成的监控文件并不直观,因此我们可以把文件转换成图标的方式去分析,也就是火焰图,具体使用的工具是Flame Graph。

# Arthas(阿尔萨斯):线上问题诊断工具

Arthas是阿里巴巴开源的一个线上问题诊断工具,可以简单理解为一个web服务+全家桶工具,如果你要使用对应的分析工具,工具底层的实现还是基于操作系统和jdk的相关分析工具,只不过在这些基础之上,它提供了Dashboard可以实时查看系统的运行状况,查看方法的入参/返回值/异常,在线热更新代码,快速定位应用的热点,生成火焰图,在线诊断,点开网页诊断线上应用。Arthas-Java 应用诊断利器 (opens new window)

# 类文件结构

# 魔数与Class文件的版本

# 魔数

类文件的前面4个字节分别是CA,FE,BA,BE,连起来是0xCAFEBABE,它的唯一作用是确定这个文件是否为 一个能被虚拟机接受的Class文件。

# Class文件的版本

紧接着魔数,第5到6个字节代表Java的次版本号,默认为0x0000,代表0,第7到8位是主版本号,0x0032, 对应十进制的50,也就是说通过主版本号可以看出对应的是jdk6。

# 常量池

常量池是一个集合,所以前面的2位字节代表常量池中有多少个常量。针对每一个常量,又有一个1字节的标志位,声明常量的类型,而针对每一个常量类型(如整型常量,浮点型常量,UTF8编码的字符串),又有不同的数据结构集合。(这块《深入理解Java虚拟机》针对常量池中的大部分常量的数据结构做了讲解,但是我们没必要一一查看,一般我们直接用javap指令查看class的常量池即可)。

# 访问标志

在常量池结束之后,我们可以看到2个字节长度的访问标志,访问标志以及标志的含义如下:

访问标志 标志值 业务含义
ACC_PUBLIC 0x0001 声明类是否是public
ACC_FINAL 0x0010 声明类是否是final
ACC_SUPER 0x0020 识别类是否是由jdk1.2以上的编译器编译
ACC_INTERFACE 0x0200 声明这是一个接口
ACC_ABSTRACT 0x0400 是否由abstract修饰
ACC_SYNTHETIC 0x1000 标明这个类不是由用户代码产生的
ACC_ANNOTATION 0x2000 标明这是一个注解
ACC_ENUM 0x4000 标明这是一个枚举
ACC_MODULE 0x8000 标明这是一个jdk9中的模块

一个使用jdk8编译的非final声明的public类,他的访问标志为ACC_PUBLIC+ACC_SUPER=0x0001 | 0x0020 = 0x0021,反之如果我们看到0x0021,怎么知道它是一个非final的public类呢? 通过比对上面的表,0x8000,0x4000,0x2000,0x1000,0x0400,0x0200均大于0x0021,因此这个类不是模块,不是枚举,不是注解,是由用户代码产生的,没有经过abstract修饰,也不是接口,那它就是一个普通的类, 0x0021>0x0020,说明它是经过jdk2以上的编译器编译的。接下来就判断它是不是final类,如果是的话,它应该是0x0031了,这里它是0x0021,说明不是final类,同理,如果类没有声明为public,它应该是0x0020,这里它是0x0021,就说明它是public。

# 类索引,父类索引与接口索引集合

# 类索引

类索引是一个2字节的数据,指向的是常量池中的常量编号,这个编号最终指向的是内容是类的全限定类名。

# 父类索引

父类索引页是一个2字节的数据,执行的是常量池中的常量编号,这个编号最终指向的是内容是类的父类的全限定类名。

# 接口索引集合

接口索引集合由一个2字节的计数器以及后面的数据集组成,我们应该有能力猜到,如果计数器为0,说明类没有声明接口实现,如果不为0,说明后面跟着一些2字节的数据,数据指向的是常量池的常量编号,最终指向的是接口的全限定名称。

# 字段表集合

Java类中的属性的集合。如private String name = "howl";字段表集合里首先会有一个计数器,显示了这个类一共有多少个属性,针对每个属性又有一个数据结构,首先会有access_flag控制类的访问权限,其次会有描述符字段,记录属性的类型,其后会有属性名称以及值的定义。

# 方法表集合

方法表集合与其他集合一致(如字段表),有一个计数器记录类里有多少方法,针对每个方法,对方法访问标志access_flag,返回值,方法名,形参进行记录。对于方法里的具体内容,则是使用了一个名为Code的索引值,指向属性表集合里的Code属性。

# 属性表集合

属性表集合也是由一个计数器后面跟多个属性表的结构,每个属性表同样有它的数据结构,如Code属性用于存储方法的方法体。

# 补充资料

# JDK8默认垃圾回收器是哪个?

# 可以看到,当前主机的jdk版本是1.8.0_92,默认使用的垃圾回收器是UseParallelGC
# ParallelGC对新生代进行YoungGC时使用Parallel Scavenge垃圾回收器
# ParallelGC对老年代进行FullGC时使用Parallel Old垃圾回收器
[root@VM-8-5-centos ~]# java -XX:+PrintCommandLineFlags -version
-XX:InitialHeapSize=30109824 -XX:MaxHeapSize=481757184 -XX:+PrintCommandLineFlags -XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX:+UseParallelGC
java version "1.8.0_92"
Java(TM) SE Runtime Environment (build 1.8.0_92-b14)
Java HotSpot(TM) 64-Bit Server VM (build 25.92-b14, mixed mode)

# JDK8中GC日志如何查看? 基于jdk8

首先如果想查看GC日志,我们在启动java进程的时候,需要告知jvm打印相关的gc日志。这样在gc的时候,jvm就会将相关日志打印到我们的指定路径下。

    1)查看GC基本信息:

查看详情
# VM参数 -Xmx1g -Xms1g -XX:+PrintGC -Xloggc:d:\\gc\\gc.log
# jdk信息
OpenJDK 64-Bit Server VM (25.382-b05) for windows-amd64 JRE (1.8.0_382-b05), built on Jul 14 2023 19:32:03 by "Administrator" with MS VC++ 12.0 (VS2013)
# 内存信息
Memory: 4k page, physical 16595576k(5893888k free), swap 19085944k(3566920k free)
# 命令行
CommandLine flags: -XX:InitialHeapSize=1073741824 -XX:MaxHeapSize=1073741824 -XX:+PrintGC -XX:+PrintGCTimeStamps -XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX:-UseLargePagesIndividualAllocation -XX:+UseParallelGC 
# 0.278 jvm启动到打印这行日志的时间
# GC (Allocation Failure) :说明触发的是YoungGC,GC原因是Allocation Failure (表明本次引起GC的原因是因为在年轻代中没有足够的空间能够存储新的数据了)
# 262144K: gc前堆大小 79933K: gc后堆大小 1005056K:堆内存总大小
# 0.0115979 secs :gc时间
0.278: [GC (Allocation Failure)  262144K->79933K(1005056K), 0.0115979 secs]
0.327: [GC (Allocation Failure)  342077K->149866K(1005056K), 0.0163560 secs]
0.378: [GC (Allocation Failure)  412010K->229232K(1005056K), 0.0242948 secs]
0.439: [GC (Allocation Failure)  491363K->296103K(1005056K), 0.0217281 secs]
0.498: [GC (Allocation Failure)  558247K->377036K(1005056K), 0.0203519 secs]
0.555: [GC (Allocation Failure)  639180K->452762K(859648K), 0.0178402 secs]
0.588: [GC (Allocation Failure)  569374K->490731K(932352K), 0.0088185 secs]
0.613: [GC (Allocation Failure)  607467K->522827K(932352K), 0.0114736 secs]
0.641: [GC (Allocation Failure)  639563K->552987K(932352K), 0.0138871 secs]
0.676: [GC (Allocation Failure)  669723K->580301K(932352K), 0.0187312 secs]
0.710: [GC (Allocation Failure)  697037K->616094K(932352K), 0.0207839 secs]
0.747: [GC (Allocation Failure)  732830K->647615K(932352K), 0.0121539 secs]
0.759: [Full GC (Ergonomics)  647615K->339162K(932352K), 0.0433159 secs]
0.821: [GC (Allocation Failure)  455898K->373798K(932352K), 0.0036993 secs]
0.843: [GC (Allocation Failure)  490534K->407945K(932352K), 0.0067399 secs]
0.866: [GC (Allocation Failure)  524681K->441273K(932352K), 0.0069481 secs]
0.889: [GC (Allocation Failure)  558009K->475437K(932352K), 0.0075319 secs]
0.912: [GC (Allocation Failure)  592173K->509551K(932352K), 0.0071908 secs]
0.937: [GC (Allocation Failure)  626287K->542725K(932352K), 0.0075182 secs]
0.961: [GC (Allocation Failure)  659461K->576139K(932352K), 0.0067951 secs]
0.987: [GC (Allocation Failure)  692875K->609600K(932352K), 0.0092748 secs]
1.021: [GC (Allocation Failure)  726336K->642594K(932352K), 0.0086655 secs]
1.054: [GC (Allocation Failure)  759330K->677239K(932352K), 0.0101295 secs]
1.064: [Full GC (Ergonomics)  677239K->353958K(932352K), 0.0429270 secs]
1.130: [GC (Allocation Failure)  470395K->393757K(932352K), 0.0040754 secs]

    2)查看GC详细信息:

查看详情
# VM参数 -Xmx1g -Xms1g -XX:+PrintGCDetails -XX:+PrintGCDateStamps -Xloggc:d:\\gc\\gc.log
# jdk版本
OpenJDK 64-Bit Server VM (25.382-b05) for windows-amd64 JRE (1.8.0_382-b05), built on Jul 14 2023 19:32:03 by "Administrator" with MS VC++ 12.0 (VS2013)
# 内存信息
Memory: 4k page, physical 16595576k(5805944k free), swap 19085944k(3607288k free)
# 命令行参数,可以看出这里使用的是jdk8默认的垃圾回收器
CommandLine flags: -XX:InitialHeapSize=1073741824 -XX:MaxHeapSize=1073741824 -XX:+PrintGC -XX:+PrintGCDateStamps -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX:-UseLargePagesIndividualAllocation -XX:+UseParallelGC 

# 2024-02-21T11:34:42.353+0800:gc开始时间 0.324:jvm启动到打印这行日志的时间

# [GC (Allocation Failure) [PSYoungGen: 262144K->43518K(305664K)] 262144K->77091K(1005056K), 0.0168742 secs]
## GC (Allocation Failure) 说明触发的是YoungGC,GC原因是Allocation Failure (表明本次引起GC的原因是因为在年轻代中没有足够的空间能够存储新的数据了)

## [PSYoungGen: 262144K->43518K(305664K)] 262144K->77091K(1005056K)
## 第一个262144K:年轻代GC前总内存占用量 43518K:年轻代GC后总内存占用量  305664K:年轻代的总内存大小
## 第二个262144K:总内存占用量(注意此时总内存占用量和young内存占用量是相等的,因为此时老年代还没有对象,所有对象在新生代)
## 77091K:GC后总内存占用量    1005056K:堆内存总大小
## 即年轻代的内存占用减少了262144K-43518K=218626K,即减少了213.5M
## 总内存占用从262144K减少到了77091K,即减少了185053K,即减少了180.7M
## 也就说明有213.5M-180.7M=32.8M的数据转移到了老年代中

## 0.0168742 secs young GC的时长是0.016秒

# [Times: user=0.02 sys=0.03, real=0.02 secs] 
## 这里打印的是GC使用的CPU时间 
2024-02-21T11:34:42.353+0800: 0.324: [GC (Allocation Failure) [PSYoungGen: 262144K->43518K(305664K)] 262144K->77091K(1005056K), 0.0168742 secs] [Times: user=0.02 sys=0.03, real=0.02 secs] 

2024-02-21T11:34:42.417+0800: 0.388: [GC (Allocation Failure) [PSYoungGen: 305662K->43516K(305664K)] 339235K->150299K(1005056K), 0.0224450 secs] [Times: user=0.03 sys=0.13, real=0.02 secs] 
2024-02-21T11:34:42.489+0800: 0.461: [GC (Allocation Failure) [PSYoungGen: 305660K->43518K(305664K)] 412443K->223931K(1005056K), 0.0172017 secs] [Times: user=0.00 sys=0.09, real=0.02 secs] 
2024-02-21T11:34:42.559+0800: 0.530: [GC (Allocation Failure) [PSYoungGen: 305662K->43503K(305664K)] 486075K->291606K(1005056K), 0.0159534 secs] [Times: user=0.08 sys=0.02, real=0.02 secs] 
2024-02-21T11:34:42.628+0800: 0.600: [GC (Allocation Failure) [PSYoungGen: 305313K->43518K(305664K)] 553416K->360748K(1005056K), 0.0179793 secs] [Times: user=0.03 sys=0.05, real=0.02 secs] 
2024-02-21T11:34:42.686+0800: 0.657: [GC (Allocation Failure) [PSYoungGen: 305662K->43517K(160256K)] 622892K->438346K(859648K), 0.0174253 secs] [Times: user=0.00 sys=0.09, real=0.02 secs] 
2024-02-21T11:34:42.727+0800: 0.698: [GC (Allocation Failure) [PSYoungGen: 160253K->70894K(232960K)] 555082K->473434K(932352K), 0.0118594 secs] [Times: user=0.02 sys=0.06, real=0.01 secs] 
2024-02-21T11:34:42.760+0800: 0.731: [GC (Allocation Failure) [PSYoungGen: 187630K->90479K(232960K)] 590170K->502602K(932352K), 0.0098620 secs] [Times: user=0.13 sys=0.00, real=0.01 secs] 
2024-02-21T11:34:42.786+0800: 0.757: [GC (Allocation Failure) [PSYoungGen: 207215K->99410K(232960K)] 619338K->531098K(932352K), 0.0120444 secs] [Times: user=0.13 sys=0.00, real=0.01 secs] 
2024-02-21T11:34:42.816+0800: 0.787: [GC (Allocation Failure) [PSYoungGen: 216146K->76074K(232960K)] 647834K->561451K(932352K), 0.0161529 secs] [Times: user=0.03 sys=0.06, real=0.02 secs] 
2024-02-21T11:34:42.849+0800: 0.821: [GC (Allocation Failure) [PSYoungGen: 192810K->39856K(232960K)] 678187K->595289K(932352K), 0.0131285 secs] [Times: user=0.03 sys=0.09, real=0.01 secs] 
2024-02-21T11:34:42.878+0800: 0.849: [GC (Allocation Failure) [PSYoungGen: 156592K->37330K(232960K)] 712025K->628828K(932352K), 0.0078177 secs] [Times: user=0.00 sys=0.00, real=0.01 secs] 
2024-02-21T11:34:42.899+0800: 0.870: [GC (Allocation Failure) [PSYoungGen: 153798K->40450K(232960K)] 745297K->664638K(932352K), 0.0085327 secs] [Times: user=0.03 sys=0.06, real=0.01 secs] 
# 这里触发了Full GC
2024-02-21T11:34:42.908+0800: 0.879: [Full GC (Ergonomics) [PSYoungGen: 40450K->0K(232960K)] [ParOldGen: 624187K->337282K(699392K)] 664638K->337282K(932352K), [Metaspace: 3566K->3566K(1056768K)], 0.0434790 secs] [Times: user=0.20 sys=0.02, real=0.04 secs] 
2024-02-21T11:34:42.970+0800: 0.941: [GC (Allocation Failure) [PSYoungGen: 116201K->39397K(232960K)] 453484K->376680K(932352K), 0.0049786 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
2024-02-21T11:34:42.994+0800: 0.966: [GC (Allocation Failure) [PSYoungGen: 155964K->38130K(232960K)] 493246K->411481K(932352K), 0.0079288 secs] [Times: user=0.09 sys=0.00, real=0.01 secs] 
2024-02-21T11:34:43.019+0800: 0.990: [GC (Allocation Failure) [PSYoungGen: 154866K->41938K(232960K)] 528217K->449761K(932352K), 0.0087039 secs] [Times: user=0.00 sys=0.01, real=0.01 secs] 
2024-02-21T11:34:43.044+0800: 1.015: [GC (Allocation Failure) [PSYoungGen: 158674K->43700K(232960K)] 566497K->488591K(932352K), 0.0120657 secs] [Times: user=0.00 sys=0.00, real=0.01 secs] 
2024-02-21T11:34:43.076+0800: 1.048: [GC (Allocation Failure) [PSYoungGen: 160436K->38791K(232960K)] 605327K->523471K(932352K), 0.0086779 secs] [Times: user=0.00 sys=0.00, real=0.01 secs] 
2024-02-21T11:34:43.107+0800: 1.079: [GC (Allocation Failure) [PSYoungGen: 155527K->35408K(232960K)] 640207K->556562K(932352K), 0.0079792 secs] [Times: user=0.00 sys=0.00, real=0.01 secs] 
2024-02-21T11:34:43.138+0800: 1.109: [GC (Allocation Failure) [PSYoungGen: 152144K->42003K(232960K)] 673298K->594580K(932352K), 0.0084023 secs] [Times: user=0.00 sys=0.00, real=0.01 secs] 
2024-02-21T11:34:43.168+0800: 1.140: [GC (Allocation Failure) [PSYoungGen: 158739K->41319K(232960K)] 711316K->632273K(932352K), 0.0093842 secs] [Times: user=0.08 sys=0.00, real=0.01 secs] 
# 堆信息
Heap
## 年轻代
PSYoungGen      total 232960K, used 55613K [0x00000000eab00000, 0x0000000100000000, 0x0000000100000000)
###伊甸园
eden space 116736K, 12% used [0x00000000eab00000,0x00000000eb8f5828,0x00000000f1d00000)
###S0
from space 116224K, 35% used [0x00000000f1d00000,0x00000000f4559e10,0x00000000f8e80000)
###S1
to   space 116224K, 0% used [0x00000000f8e80000,0x00000000f8e80000,0x0000000100000000)
## 老年代
ParOldGen       total 699392K, used 590953K [0x00000000c0000000, 0x00000000eab00000, 0x00000000eab00000)
object space 699392K, 84% used [0x00000000c0000000,0x00000000e411a718,0x00000000eab00000)
# 元空间大小
Metaspace       used 4055K, capacity 4572K, committed 4864K, reserved 1056768K
class space    used 439K, capacity 460K, committed 512K, reserved 1048576K

    3)查看GC前后的堆,元空间的可用容量变化:

查看详情
# VM参数 -Xmx1g -Xms1g -XX:+PrintHeapAtGC -Xloggc:d:\\gc\\gc.log
OpenJDK 64-Bit Server VM (25.382-b05) for windows-amd64 JRE (1.8.0_382-b05), built on Jul 14 2023 19:32:03 by "Administrator" with MS VC++ 12.0 (VS2013)
Memory: 4k page, physical 16595576k(6587980k free), swap 19085944k(4172504k free)
CommandLine flags: -XX:InitialHeapSize=1073741824 -XX:MaxHeapSize=1073741824 -XX:+PrintGC -XX:+PrintGCTimeStamps -XX:+PrintHeapAtGC -XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX:-UseLargePagesIndividualAllocation -XX:+UseParallelGC 
{
# GC之前    
Heap before GC invocations=1 (full 0):
 PSYoungGen      total 305664K, used 262144K [0x00000000eab00000, 0x0000000100000000, 0x0000000100000000)
  eden space 262144K, 100% used [0x00000000eab00000,0x00000000fab00000,0x00000000fab00000)
  from space 43520K, 0% used [0x00000000fd580000,0x00000000fd580000,0x0000000100000000)
  to   space 43520K, 0% used [0x00000000fab00000,0x00000000fab00000,0x00000000fd580000)
 ParOldGen       total 699392K, used 0K [0x00000000c0000000, 0x00000000eab00000, 0x00000000eab00000)
  object space 699392K, 0% used [0x00000000c0000000,0x00000000c0000000,0x00000000eab00000)
 Metaspace       used 3565K, capacity 4500K, committed 4864K, reserved 1056768K
  class space    used 382K, capacity 388K, committed 512K, reserved 1048576K
0.241: [GC (Allocation Failure)  262144K->78361K(1005056K), 0.0121320 secs]
# GC之后
Heap after GC invocations=1 (full 0):
 PSYoungGen      total 305664K, used 43512K [0x00000000eab00000, 0x0000000100000000, 0x0000000100000000)
  eden space 262144K, 0% used [0x00000000eab00000,0x00000000eab00000,0x00000000fab00000)
  from space 43520K, 99% used [0x00000000fab00000,0x00000000fd57e0a8,0x00000000fd580000)
  to   space 43520K, 0% used [0x00000000fd580000,0x00000000fd580000,0x0000000100000000)
 ParOldGen       total 699392K, used 34848K [0x00000000c0000000, 0x00000000eab00000, 0x00000000eab00000)
  object space 699392K, 4% used [0x00000000c0000000,0x00000000c2208398,0x00000000eab00000)
 Metaspace       used 3565K, capacity 4500K, committed 4864K, reserved 1056768K
  class space    used 382K, capacity 388K, committed 512K, reserved 1048576K
}

    4)查看GC过程中用户线程并发时间以及停顿的时间:

查看详情
# VM参数 -Xmx1g -Xms1g -XX:+PrintGCApplicationConcurrentTime -XX:+PrintGCApplicationStoppedTime -Xloggc:d:\\gc\\gc.log
OpenJDK 64-Bit Server VM (25.382-b05) for windows-amd64 JRE (1.8.0_382-b05), built on Jul 14 2023 19:32:03 by "Administrator" with MS VC++ 12.0 (VS2013)
Memory: 4k page, physical 16595576k(6794292k free), swap 19085944k(5061560k free)
CommandLine flags: -XX:InitialHeapSize=1073741824 -XX:MaxHeapSize=1073741824 -XX:+PrintGC -XX:+PrintGCApplicationConcurrentTime -XX:+PrintGCApplicationStoppedTime -XX:+PrintGCTimeStamps -XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX:-UseLargePagesIndividualAllocation -XX:+UseParallelGC 
0.241: Application time: 0.1211784 seconds
0.241: [GC (Allocation Failure)  262139K->79293K(1005056K), 0.0105698 secs]
0.251: Total time for which application threads were stopped: 0.0107120 seconds, Stopping threads took: 0.0000281 seconds
0.288: Application time: 0.0369675 seconds
0.288: [GC (Allocation Failure)  341437K->153413K(1005056K), 0.0169709 secs]
0.305: Total time for which application threads were stopped: 0.0170923 seconds, Stopping threads took: 0.0000180 seconds
0.341: Application time: 0.0351123 seconds
0.341: [GC (Allocation Failure)  415557K->229917K(1005056K), 0.0153684 secs]
0.356: Total time for which application threads were stopped: 0.0154998 seconds, Stopping threads took: 0.0000198 seconds
0.393: Application time: 0.0372498 seconds
0.393: [GC (Allocation Failure)  492061K->302571K(1005056K), 0.0142356 secs]
0.408: Total time for which application threads were stopped: 0.0143573 seconds, Stopping threads took: 0.0000294 seconds
0.438: Application time: 0.0305803 seconds
0.438: [GC (Allocation Failure)  564715K->375184K(1005056K), 0.0152272 secs]
0.454: Total time for which application threads were stopped: 0.0153396 seconds, Stopping threads took: 0.0000206 seconds
0.487: Application time: 0.0337708 seconds
0.487: [GC (Allocation Failure)  637032K->446393K(859648K), 0.0142464 secs]
0.502: Total time for which application threads were stopped: 0.0143478 seconds, Stopping threads took: 0.0000203 seconds
0.515: Application time: 0.0136287 seconds
0.515: [GC (Allocation Failure)  563129K->489440K(932352K), 0.0108081 secs]
0.526: Total time for which application threads were stopped: 0.0109639 seconds, Stopping threads took: 0.0000375 seconds
0.545: Application time: 0.0185320 seconds
0.545: [GC (Allocation Failure)  606176K->520773K(932352K), 0.0115452 secs]
0.556: Total time for which application threads were stopped: 0.0116785 seconds, Stopping threads took: 0.0000268 seconds
0.572: Application time: 0.0155752 seconds
0.572: [GC (Allocation Failure)  637509K->554604K(932352K), 0.0163587 secs]
0.589: Total time for which application threads were stopped: 0.0164878 seconds, Stopping threads took: 0.0000230 seconds
0.619: Application time: 0.0302316 seconds
0.619: [GC (Allocation Failure)  671340K->583022K(932352K), 0.0222525 secs]
0.641: Total time for which application threads were stopped: 0.0224211 seconds, Stopping threads took: 0.0000380 seconds
0.667: Application time: 0.0258690 seconds
0.667: [GC (Allocation Failure)  699721K->612671K(932352K), 0.0161022 secs]
0.683: Total time for which application threads were stopped: 0.0162566 seconds, Stopping threads took: 0.0000319 seconds
0.701: Application time: 0.0175546 seconds
0.701: [GC (Allocation Failure)  729390K->644371K(932352K), 0.0080362 secs]
0.709: [Full GC (Ergonomics)  644371K->338491K(932352K), 0.0435653 secs]
0.753: Total time for which application threads were stopped: 0.0518384 seconds, Stopping threads took: 0.0000214 seconds
0.776: Application time: 0.0229623 seconds
0.776: [GC (Allocation Failure)  454969K->375916K(932352K), 0.0053884 secs]
0.781: Total time for which application threads were stopped: 0.0055923 seconds, Stopping threads took: 0.0000608 seconds
0.800: Application time: 0.0187336 seconds
0.800: [GC (Allocation Failure)  492286K->414216K(932352K), 0.0078718 secs]
0.808: Total time for which application threads were stopped: 0.0079946 seconds, Stopping threads took: 0.0000279 seconds
0.828: Application time: 0.0198064 seconds
0.828: [GC (Allocation Failure)  530952K->452583K(932352K), 0.0095949 secs]
0.838: Total time for which application threads were stopped: 0.0097809 seconds, Stopping threads took: 0.0000471 seconds
0.858: Application time: 0.0204690 seconds
0.858: [GC (Allocation Failure)  569319K->486930K(932352K), 0.0117822 secs]
0.870: Total time for which application threads were stopped: 0.0119662 seconds, Stopping threads took: 0.0000374 seconds
0.889: Application time: 0.0192734 seconds
0.889: [GC (Allocation Failure)  603287K->522246K(932352K), 0.0104330 secs]
0.900: Total time for which application threads were stopped: 0.0106177 seconds, Stopping threads took: 0.0000300 seconds
0.923: Application time: 0.0233277 seconds
0.923: [GC (Allocation Failure)  638982K->558575K(932352K), 0.0102558 secs]
0.934: Total time for which application threads were stopped: 0.0103861 seconds, Stopping threads took: 0.0000214 seconds
0.954: Application time: 0.0198954 seconds
0.954: [GC (Allocation Failure)  675311K->599026K(932352K), 0.0108273 secs]
0.965: Total time for which application threads were stopped: 0.0109825 seconds, Stopping threads took: 0.0000223 seconds
0.986: Application time: 0.0213374 seconds
0.986: [GC (Allocation Failure)  715762K->629449K(932352K), 0.0103810 secs]
0.996: Total time for which application threads were stopped: 0.0105217 seconds, Stopping threads took: 0.0000235 seconds
1.020: Application time: 0.0234059 seconds
1.020: [GC (Allocation Failure)  746185K->661193K(932352K), 0.0120998 secs]
1.032: [Full GC (Ergonomics)  661193K->354043K(932352K), 0.0492329 secs]
1.082: Total time for which application threads were stopped: 0.0616539 seconds, Stopping threads took: 0.0000518 seconds
1.112: Application time: 0.0307599 seconds
1.112: [GC (Allocation Failure)  470755K->395681K(932352K), 0.0047586 secs]
1.117: Total time for which application threads were stopped: 0.0049199 seconds, Stopping threads took: 0.0000277 seconds
1.122: Application time: 0.0048925 seconds

    5)查看收集器的Ergonomics(自适应)机制:

查看详情
# Ergonomics机制:自动设置堆空间各分代区域大小、收集目标等内容。
# VM参数 -Xmx1g -Xms1g -XX:+PrintAdaptiveSizePolicy -Xloggc:d:\\gc\\gc.log
OpenJDK 64-Bit Server VM (25.382-b05) for windows-amd64 JRE (1.8.0_382-b05), built on Jul 14 2023 19:32:03 by "Administrator" with MS VC++ 12.0 (VS2013)
Memory: 4k page, physical 16595576k(6834016k free), swap 19085944k(5030536k free)
CommandLine flags: -XX:InitialHeapSize=1073741824 -XX:MaxHeapSize=1073741824 -XX:+PrintAdaptiveSizePolicy -XX:+PrintGC -XX:+PrintGCTimeStamps -XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX:-UseLargePagesIndividualAllocation -XX:+UseParallelGC 
0.234: [GC (Allocation Failure) AdaptiveSizePolicy::update_averages:  survived: 44552080  promoted: 37943600  overflow: true
AdaptiveSizeStart: 0.244 collection: 1 
PSAdaptiveSizePolicy::compute_eden_space_size limits: desired_eden_size: 536870912 old_eden_size: 268435456 eden_limit: 268435456 cur_eden: 268435456 max_eden_size: 268435456 avg_young_live: 44552080
PSAdaptiveSizePolicy::compute_eden_space_size: costs minor_time: 0.045314 major_cost: 0.000000 mutator_cost: 0.954686 throughput_goal: 0.990000 live_space: 312987520 free_space: 536870912 old_eden_size: 268435456 desired_eden_size: 268435456
AdaptiveSizeStop: collection: 1 
 262144K->80562K(1005056K), 0.0108073 secs]
0.281: [GC (Allocation Failure) AdaptiveSizePolicy::update_averages:  survived: 44563096  promoted: 67969344  overflow: true
AdaptiveSizeStart: 0.295 collection: 2 
PSAdaptiveSizePolicy::compute_eden_space_size limits: desired_eden_size: 536870912 old_eden_size: 268435456 eden_limit: 268435456 cur_eden: 268435456 max_eden_size: 268435456 avg_young_live: 44557588
PSAdaptiveSizePolicy::compute_eden_space_size: costs minor_time: 0.162842 major_cost: 0.000000 mutator_cost: 0.837158 throughput_goal: 0.990000 live_space: 312993056 free_space: 536870912 old_eden_size: 268435456 desired_eden_size: 268435456
AdaptiveSizeStop: collection: 2 
 342706K->146949K(1005056K), 0.0142459 secs]
0.330: [GC (Allocation Failure) AdaptiveSizePolicy::update_averages:  survived: 44562704  promoted: 77478048  overflow: true
AdaptiveSizeStart: 0.345 collection: 3 
PSAdaptiveSizePolicy::compute_eden_space_size limits: desired_eden_size: 536870912 old_eden_size: 268435456 eden_limit: 268435456 cur_eden: 268435456 max_eden_size: 268435456 avg_young_live: 44559276
PSAdaptiveSizePolicy::compute_eden_space_size: costs minor_time: 0.205801 major_cost: 0.000000 mutator_cost: 0.794199 throughput_goal: 0.990000 live_space: 312994720 free_space: 536870912 old_eden_size: 268435456 desired_eden_size: 268435456
AdaptiveSizeStop: collection: 3 
 409093K->222611K(1005056K), 0.0146753 secs]
0.378: [GC (Allocation Failure) AdaptiveSizePolicy::update_averages:  survived: 44564232  promoted: 78595848  overflow: true
AdaptiveSizeStart: 0.392 collection: 4 
PSAdaptiveSizePolicy::compute_eden_space_size limits: desired_eden_size: 536870912 old_eden_size: 268435456 eden_limit: 268435456 cur_eden: 268435456 max_eden_size: 268435456 avg_young_live: 44560516
PSAdaptiveSizePolicy::compute_eden_space_size: costs minor_time: 0.228406 major_cost: 0.000000 mutator_cost: 0.771594 throughput_goal: 0.990000 live_space: 312995968 free_space: 536870912 old_eden_size: 268435456 desired_eden_size: 268435456
AdaptiveSizeStop: collection: 4 
 484755K->299366K(1005056K), 0.0141805 secs]
0.426: [GC (Allocation Failure) AdaptiveSizePolicy::update_averages:  survived: 44564480  promoted: 73591912  overflow: true
AdaptiveSizeStart: 0.440 collection: 5 
  avg_survived_padded_avg: 142260752.000000  avg_promoted_padded_avg: 97689952.000000  avg_pretenured_padded_avg: 0.000000  tenuring_thresh: 6  target_size: 119013376
PSAdaptiveSizePolicy::compute_eden_space_size limits: desired_eden_size: 536870912 old_eden_size: 268435456 eden_limit: 268435456 cur_eden: 268435456 max_eden_size: 268435456 avg_young_live: 44561308
PSAdaptiveSizePolicy::compute_eden_space_size: costs minor_time: 0.244537 major_cost: 0.000000 mutator_cost: 0.755463 throughput_goal: 0.990000 live_space: 312996768 free_space: 536870912 old_eden_size: 268435456 desired_eden_size: 268435456
AdaptiveSizePolicy::survivor space sizes: collection: 5 (44564480, 44564480) -> (44564480, 44564480) 
AdaptiveSizeStop: collection: 5 
 561510K->371233K(1005056K), 0.0141221 secs]
0.477: [GC (Allocation Failure) AdaptiveSizePolicy::update_averages:  survived: 44550296  promoted: 73790120  overflow: true
AdaptiveSizeStart: 0.490 collection: 6 
  avg_survived_padded_avg: 141139936.000000  avg_promoted_padded_avg: 96576856.000000  avg_pretenured_padded_avg: 0.000000  tenuring_thresh: 5  target_size: 119013376
PSAdaptiveSizePolicy::compute_eden_space_size limits: desired_eden_size: 536870912 old_eden_size: 268435456 eden_limit: 268435456 cur_eden: 268435456 max_eden_size: 268435456 avg_young_live: 44559548
PSAdaptiveSizePolicy::compute_eden_space_size: costs minor_time: 0.251404 major_cost: 0.000000 mutator_cost: 0.748596 throughput_goal: 0.990000 live_space: 312995008 free_space: 536870912 old_eden_size: 268435456 desired_eden_size: 268435456
AdaptiveSizePolicy::survivor space sizes: collection: 6 (44564480, 44564480) -> (44564480, 119013376) 
AdaptiveSizeStop: collection: 6 
 632960K->443280K(859648K), 0.0136410 secs]
0.505: [GC (Allocation Failure) AdaptiveSizePolicy::update_averages:  survived: 72391944  promoted: 6189912  overflow: false
AdaptiveSizeStart: 0.514 collection: 7 
  avg_survived_padded_avg: 146075200.000000  avg_promoted_padded_avg: 106299944.000000  avg_pretenured_padded_avg: 0.000000  tenuring_thresh: 4  target_size: 119013376
PSAdaptiveSizePolicy::compute_eden_space_size limits: desired_eden_size: 239075328 old_eden_size: 268435456 eden_limit: 193986560 cur_eden: 119537664 max_eden_size: 193986560 avg_young_live: 48456084
PSAdaptiveSizePolicy::compute_eden_space_size: costs minor_time: 0.277959 major_cost: 0.000000 mutator_cost: 0.722041 throughput_goal: 0.990000 live_space: 316891552 free_space: 536870912 old_eden_size: 268435456 desired_eden_size: 193986560
AdaptiveSizePolicy::survivor space sizes: collection: 7 (119013376, 44564480) -> (119013376, 119013376) 
AdaptiveSizeStop: collection: 7 
 559960K->476514K(932352K), 0.0085090 secs]
0.532: [GC (Allocation Failure) AdaptiveSizePolicy::update_averages:  survived: 97004576  promoted: 11840224  overflow: false
AdaptiveSizeStart: 0.544 collection: 8 
  avg_survived_padded_avg: 143371840.000000  avg_promoted_padded_avg: 110053616.000000  avg_pretenured_padded_avg: 0.000000  tenuring_thresh: 3  target_size: 119013376
PSAdaptiveSizePolicy::compute_eden_space_size limits: desired_eden_size: 239075328 old_eden_size: 193986560 eden_limit: 119537664 cur_eden: 119537664 max_eden_size: 119537664 avg_young_live: 54281904
PSAdaptiveSizePolicy::compute_eden_space_size: costs minor_time: 0.308969 major_cost: 0.000000 mutator_cost: 0.691031 throughput_goal: 0.990000 live_space: 322717376 free_space: 462422016 old_eden_size: 193986560 desired_eden_size: 119537664
AdaptiveSizeStop: collection: 8 
 592990K->512112K(932352K), 0.0122454 secs]
0.560: [GC (Allocation Failure) AdaptiveSizePolicy::update_averages:  survived: 113566768  promoted: 16035976  overflow: false
AdaptiveSizeStart: 0.573 collection: 9 
  avg_survived_padded_avg: 142359072.000000  avg_promoted_padded_avg: 110789344.000000  avg_pretenured_padded_avg: 0.000000  tenuring_thresh: 2  target_size: 119013376
PSAdaptiveSizePolicy::compute_eden_space_size limits: desired_eden_size: 191365120 old_eden_size: 119537664 eden_limit: 119537664 cur_eden: 119537664 max_eden_size: 119537664 avg_young_live: 60803240
PSAdaptiveSizePolicy::compute_eden_space_size: costs minor_time: 0.345341 major_cost: 0.000000 mutator_cost: 0.654659 throughput_goal: 0.990000 live_space: 329238688 free_space: 387973120 old_eden_size: 119537664 desired_eden_size: 119537664
AdaptiveSizeStop: collection: 9 
 628848K->543947K(932352K), 0.0134943 secs]
0.589: [GC (Allocation Failure) AdaptiveSizePolicy::update_averages:  survived: 76792776  promoted: 63616992  overflow: false
AdaptiveSizeStart: 0.605 collection: 10 
  avg_survived_padded_avg: 143877600.000000  avg_promoted_padded_avg: 109855440.000000  avg_pretenured_padded_avg: 0.000000  tenuring_thresh: 1  target_size: 119013376
PSAdaptiveSizePolicy::compute_eden_space_size limits: desired_eden_size: 191365120 old_eden_size: 119537664 eden_limit: 119537664 cur_eden: 119537664 max_eden_size: 119537664 avg_young_live: 62402196
PSAdaptiveSizePolicy::compute_eden_space_size: costs minor_time: 0.383562 major_cost: 0.000000 mutator_cost: 0.616438 throughput_goal: 0.990000 live_space: 330837664 free_space: 387973120 old_eden_size: 119537664 desired_eden_size: 119537664
AdaptiveSizeStop: collection: 10 
 660353K->570160K(932352K), 0.0159447 secs]
0.620: [GC (Allocation Failure) AdaptiveSizePolicy::update_averages:  survived: 41018992  promoted: 66852408  overflow: false
AdaptiveSizeStart: 0.632 collection: 11 
  avg_survived_padded_avg: 150518272.000000  avg_promoted_padded_avg: 109833688.000000  avg_pretenured_padded_avg: 0.000000  tenuring_thresh: 1  target_size: 119013376
PSAdaptiveSizePolicy::compute_eden_space_size limits: desired_eden_size: 191365120 old_eden_size: 119537664 eden_limit: 119537664 cur_eden: 119537664 max_eden_size: 119537664 avg_young_live: 60263876
PSAdaptiveSizePolicy::compute_eden_space_size: costs minor_time: 0.403822 major_cost: 0.000000 mutator_cost: 0.596178 throughput_goal: 0.990000 live_space: 328699328 free_space: 387973120 old_eden_size: 119537664 desired_eden_size: 119537664
AdaptiveSizeStop: collection: 11 
 686783K->600511K(932352K), 0.0126882 secs]
0.648: [GC (Allocation Failure) AdaptiveSizePolicy::update_averages:  survived: 37061704  promoted: 38506616  overflow: false
AdaptiveSizeStart: 0.656 collection: 12 
  avg_survived_padded_avg: 155474976.000000  avg_promoted_padded_avg: 106503648.000000  avg_pretenured_padded_avg: 0.000000  tenuring_thresh: 1  target_size: 119013376
PSAdaptiveSizePolicy::compute_eden_space_size limits: desired_eden_size: 191365120 old_eden_size: 119537664 eden_limit: 119537664 cur_eden: 119537664 max_eden_size: 119537664 avg_young_live: 57943660
PSAdaptiveSizePolicy::compute_eden_space_size: costs minor_time: 0.392894 major_cost: 0.000000 mutator_cost: 0.607106 throughput_goal: 0.990000 live_space: 326379104 free_space: 387973120 old_eden_size: 119537664 desired_eden_size: 119537664
AdaptiveSizeStop: collection: 12 
 716830K->634250K(932352K), 0.0086502 secs]
0.656: [Full GC (Ergonomics) AdaptiveSizeStart: 0.701 collection: 13 
PSAdaptiveSizePolicy::compute_eden_space_size limits: desired_eden_size: 181293760 old_eden_size: 119537664 eden_limit: 119537664 cur_eden: 119537664 max_eden_size: 119537664 avg_young_live: 52149296
PSAdaptiveSizePolicy::compute_eden_space_size: costs minor_time: 0.392894 major_cost: 0.064074 mutator_cost: 0.543032 throughput_goal: 0.990000 live_space: 320584768 free_space: 387973120 old_eden_size: 119537664 desired_eden_size: 119537664
PSAdaptiveSizePolicy::compute_old_gen_free_space: costs minor_time: 0.392894 major_cost: 0.064074 mutator_cost: 0.543032 throughput_goal: 0.990000 live_space: 664859904 free_space: 387973120 old_promo_size: 268435456 desired_promo_size: 306184192
AdaptiveSizeStop: collection: 13 
 634250K->336206K(932352K), 0.0444051 secs]
0.722: [GC (Allocation Failure) AdaptiveSizePolicy::update_averages:  survived: 41951584  promoted: 0  overflow: false
AdaptiveSizeStart: 0.726 collection: 14 
  avg_survived_padded_avg: 157474496.000000  avg_promoted_padded_avg: 101385424.000000  avg_pretenured_padded_avg: 0.000000  tenuring_thresh: 1  target_size: 119013376
PSAdaptiveSizePolicy::compute_eden_space_size limits: desired_eden_size: 179045570 old_eden_size: 119537664 eden_limit: 119537664 cur_eden: 119537664 max_eden_size: 119537664 avg_young_live: 51129524
PSAdaptiveSizePolicy::compute_eden_space_size: costs minor_time: 0.309502 major_cost: 0.064074 mutator_cost: 0.626424 throughput_goal: 0.990000 live_space: 663840128 free_space: 425721856 old_eden_size: 119537664 desired_eden_size: 119537664
AdaptiveSizeStop: collection: 14 
 452942K->377174K(932352K), 0.0042206 secs]
0.744: [GC (Allocation Failure) AdaptiveSizePolicy::update_averages:  survived: 35092488  promoted: 37479288  overflow: false
AdaptiveSizeStart: 0.751 collection: 15 
  avg_survived_padded_avg: 159104928.000000  avg_promoted_padded_avg: 97312672.000000  avg_pretenured_padded_avg: 0.000000  tenuring_thresh: 1  target_size: 119013376
PSAdaptiveSizePolicy::compute_eden_space_size limits: desired_eden_size: 178942953 old_eden_size: 119537664 eden_limit: 119537664 cur_eden: 119537664 max_eden_size: 119537664 avg_young_live: 49525820
PSAdaptiveSizePolicy::compute_eden_space_size: costs minor_time: 0.306416 major_cost: 0.064074 mutator_cost: 0.629510 throughput_goal: 0.990000 live_space: 662236416 free_space: 425721856 old_eden_size: 119537664 desired_eden_size: 119537664
AdaptiveSizeStop: collection: 15 
 493910K->407077K(932352K), 0.0075022 secs]
0.767: [GC (Allocation Failure) AdaptiveSizePolicy::update_averages:  survived: 35979192  promoted: 32492792  overflow: false
AdaptiveSizeStart: 0.774 collection: 16 
  avg_survived_padded_avg: 159034720.000000  avg_promoted_padded_avg: 94263112.000000  avg_pretenured_padded_avg: 0.000000  tenuring_thresh: 1  target_size: 119013376
PSAdaptiveSizePolicy::compute_eden_space_size limits: desired_eden_size: 178949295 old_eden_size: 119537664 eden_limit: 119537664 cur_eden: 119537664 max_eden_size: 119537664 avg_young_live: 48171160
PSAdaptiveSizePolicy::compute_eden_space_size: costs minor_time: 0.306605 major_cost: 0.064074 mutator_cost: 0.629321 throughput_goal: 0.990000 live_space: 660881792 free_space: 425721856 old_eden_size: 119537664 desired_eden_size: 119537664
AdaptiveSizeStop: collection: 16 
 523813K->439674K(932352K), 0.0069974 secs]
0.793: [GC (Allocation Failure) AdaptiveSizePolicy::update_averages:  survived: 47231680  promoted: 29652504  overflow: false
AdaptiveSizeStart: 0.800 collection: 17 
  avg_survived_padded_avg: 155834368.000000  avg_promoted_padded_avg: 91658112.000000  avg_pretenured_padded_avg: 0.000000  tenuring_thresh: 1  target_size: 119013376
PSAdaptiveSizePolicy::compute_eden_space_size limits: desired_eden_size: 178748496 old_eden_size: 119537664 eden_limit: 119537664 cur_eden: 119537664 max_eden_size: 119537664 avg_young_live: 48077212
PSAdaptiveSizePolicy::compute_eden_space_size: costs minor_time: 0.300706 major_cost: 0.064074 mutator_cost: 0.635220 throughput_goal: 0.990000 live_space: 660787840 free_space: 425721856 old_eden_size: 119537664 desired_eden_size: 119537664
AdaptiveSizeStop: collection: 17 
 556410K->479620K(932352K), 0.0076411 secs]
0.817: [GC (Allocation Failure) AdaptiveSizePolicy::update_averages:  survived: 40476824  promoted: 38181032  overflow: false
AdaptiveSizeStart: 0.825 collection: 18 
  avg_survived_padded_avg: 153304384.000000  avg_promoted_padded_avg: 87478160.000000  avg_pretenured_padded_avg: 0.000000  tenuring_thresh: 1  target_size: 119013376
PSAdaptiveSizePolicy::compute_eden_space_size limits: desired_eden_size: 159373614 old_eden_size: 119537664 eden_limit: 119537664 cur_eden: 119537664 max_eden_size: 119537664 avg_young_live: 47317172
PSAdaptiveSizePolicy::compute_eden_space_size: costs minor_time: 0.303917 major_cost: 0.064074 mutator_cost: 0.632009 throughput_goal: 0.990000 live_space: 660027776 free_space: 425721856 old_eden_size: 119537664 desired_eden_size: 119537664
AdaptiveSizeStop: collection: 18 
 596356K->510310K(932352K), 0.0078006 secs]
0.840: [GC (Allocation Failure) AdaptiveSizePolicy::update_averages:  survived: 48839848  promoted: 35312184  overflow: false
AdaptiveSizeStart: 0.849 collection: 19 
  avg_survived_padded_avg: 148705104.000000  avg_promoted_padded_avg: 84087128.000000  avg_pretenured_padded_avg: 0.000000  tenuring_thresh: 1  target_size: 119013376
PSAdaptiveSizePolicy::compute_eden_space_size limits: desired_eden_size: 159660439 old_eden_size: 119537664 eden_limit: 119537664 cur_eden: 119537664 max_eden_size: 119537664 avg_young_live: 47469440
PSAdaptiveSizePolicy::compute_eden_space_size: costs minor_time: 0.316929 major_cost: 0.064074 mutator_cost: 0.618997 throughput_goal: 0.990000 live_space: 660180032 free_space: 425721856 old_eden_size: 119537664 desired_eden_size: 119537664
AdaptiveSizeStop: collection: 19 
 627046K->552961K(932352K), 0.0085153 secs]
0.866: [GC (Allocation Failure) AdaptiveSizePolicy::update_averages:  survived: 44090224  promoted: 41026912  overflow: false
AdaptiveSizeStart: 0.874 collection: 20 
  avg_survived_padded_avg: 144788464.000000  avg_promoted_padded_avg: 79881144.000000  avg_pretenured_padded_avg: 0.000000  tenuring_thresh: 1  target_size: 119013376
PSAdaptiveSizePolicy::compute_eden_space_size limits: desired_eden_size: 159678881 old_eden_size: 119537664 eden_limit: 119537664 cur_eden: 119537664 max_eden_size: 119537664 avg_young_live: 47131520
PSAdaptiveSizePolicy::compute_eden_space_size: costs minor_time: 0.317797 major_cost: 0.064074 mutator_cost: 0.618129 throughput_goal: 0.990000 live_space: 659842112 free_space: 425721856 old_eden_size: 119537664 desired_eden_size: 119537664
AdaptiveSizeStop: collection: 20 
 669697K->588388K(932352K), 0.0082118 secs]
0.891: [GC (Allocation Failure) AdaptiveSizePolicy::update_averages:  survived: 37828360  promoted: 41513288  overflow: false
AdaptiveSizeStart: 0.899 collection: 21 
  avg_survived_padded_avg: 141673536.000000  avg_promoted_padded_avg: 76085648.000000  avg_pretenured_padded_avg: 0.000000  tenuring_thresh: 1  target_size: 119013376
PSAdaptiveSizePolicy::compute_eden_space_size limits: desired_eden_size: 159734360 old_eden_size: 119537664 eden_limit: 119537664 cur_eden: 119537664 max_eden_size: 119537664 avg_young_live: 46201204
PSAdaptiveSizePolicy::compute_eden_space_size: costs minor_time: 0.320432 major_cost: 0.064074 mutator_cost: 0.615493 throughput_goal: 0.990000 live_space: 658911808 free_space: 425721856 old_eden_size: 119537664 desired_eden_size: 119537664
AdaptiveSizeStop: collection: 21 
 705124K->622813K(932352K), 0.0083924 secs]
0.917: [GC (Allocation Failure) AdaptiveSizePolicy::update_averages:  survived: 39744288  promoted: 32501456  overflow: false
AdaptiveSizeStart: 0.924 collection: 22 
  avg_survived_padded_avg: 137786272.000000  avg_promoted_padded_avg: 74123264.000000  avg_pretenured_padded_avg: 0.000000  tenuring_thresh: 1  target_size: 119013376
PSAdaptiveSizePolicy::compute_eden_space_size limits: desired_eden_size: 159642726 old_eden_size: 119537664 eden_limit: 119537664 cur_eden: 119537664 max_eden_size: 119537664 avg_young_live: 45555512
PSAdaptiveSizePolicy::compute_eden_space_size: costs minor_time: 0.316098 major_cost: 0.064074 mutator_cost: 0.619827 throughput_goal: 0.990000 live_space: 658266112 free_space: 425721856 old_eden_size: 119537664 desired_eden_size: 119537664
AdaptiveSizeStop: collection: 22 
 739549K->656424K(932352K), 0.0075764 secs]
0.940: [GC (Allocation Failure) AdaptiveSizePolicy::update_averages:  survived: 37612048  promoted: 37175600  overflow: false
AdaptiveSizeStart: 0.950 collection: 23 
  avg_survived_padded_avg: 134019656.000000  avg_promoted_padded_avg: 71322912.000000  avg_pretenured_padded_avg: 0.000000  tenuring_thresh: 1  target_size: 119013376
PSAdaptiveSizePolicy::compute_eden_space_size limits: desired_eden_size: 159848339 old_eden_size: 119537664 eden_limit: 119537664 cur_eden: 119537664 max_eden_size: 119537664 avg_young_live: 44761164
PSAdaptiveSizePolicy::compute_eden_space_size: costs minor_time: 0.325963 major_cost: 0.064074 mutator_cost: 0.609962 throughput_goal: 0.990000 live_space: 657471744 free_space: 425721856 old_eden_size: 119537664 desired_eden_size: 119537664
AdaptiveSizeStop: collection: 23 
 773160K->690646K(932352K), 0.0090992 secs]
0.950: [Full GC (Ergonomics) AdaptiveSizeStart: 0.993 collection: 24 
PSAdaptiveSizePolicy::compute_eden_space_size limits: desired_eden_size: 155944439 old_eden_size: 119537664 eden_limit: 119537664 cur_eden: 119537664 max_eden_size: 119537664 avg_young_live: 40285048
PSAdaptiveSizePolicy::compute_eden_space_size: costs minor_time: 0.325963 major_cost: 0.105898 mutator_cost: 0.568139 throughput_goal: 0.990000 live_space: 652995648 free_space: 425721856 old_eden_size: 119537664 desired_eden_size: 119537664
PSAdaptiveSizePolicy::compute_old_gen_free_space limits: desired_promo_size: 381264507 promo_limit: 353772352 free_in_old_gen: 353772352 max_old_gen_size: 716177408 avg_old_live: 362405056
PSAdaptiveSizePolicy::compute_old_gen_free_space: costs minor_time: 0.325963 major_cost: 0.105898 mutator_cost: 0.568139 throughput_goal: 0.990000 live_space: 671125568 free_space: 425721856 old_promo_size: 306184192 desired_promo_size: 353370112
AdaptiveSizeStop: collection: 24 
 690646K->371616K(932352K), 0.0432581 secs]
1.020: [GC (Allocation Failure) AdaptiveSizePolicy::update_averages:  survived: 38311432  promoted: 8192  overflow: false
AdaptiveSizeStart: 1.024 collection: 25 
  avg_survived_padded_avg: 129885712.000000  avg_promoted_padded_avg: 75031608.000000  avg_pretenured_padded_avg: 0.000000  tenuring_thresh: 1  target_size: 119013376
PSAdaptiveSizePolicy::compute_eden_space_size limits: desired_eden_size: 153717394 old_eden_size: 119537664 eden_limit: 119537664 cur_eden: 119537664 max_eden_size: 119537664 avg_young_live: 40087688
PSAdaptiveSizePolicy::compute_eden_space_size: costs minor_time: 0.257533 major_cost: 0.105898 mutator_cost: 0.636569 throughput_goal: 0.990000 live_space: 670928192 free_space: 472907776 old_eden_size: 119537664 desired_eden_size: 119537664
AdaptiveSizeStop: collection: 25 
 488352K->409037K(932352K), 0.0039676 secs]
1.046: [GC (Allocation Failure) AdaptiveSizePolicy::update_averages:  survived: 43755936  promoted: 34531744  overflow: false
AdaptiveSizeStart: 1.055 collection: 26 
  avg_survived_padded_avg: 124695920.000000  avg_promoted_padded_avg: 71416416.000000  avg_pretenured_padded_avg: 0.000000  tenuring_thresh: 1  target_size: 119013376
PSAdaptiveSizePolicy::compute_eden_space_size limits: desired_eden_size: 153947657 old_eden_size: 119537664 eden_limit: 119537664 cur_eden: 119537664 max_eden_size: 119537664 avg_young_live: 40454512
PSAdaptiveSizePolicy::compute_eden_space_size: costs minor_time: 0.263586 major_cost: 0.105898 mutator_cost: 0.630516 throughput_goal: 0.990000 live_space: 671295040 free_space: 472907776 old_eden_size: 119537664 desired_eden_size: 119537664
AdaptiveSizeStop: collection: 26 
 525773K->448076K(932352K), 0.0087297 secs]
1.073: [GC (Allocation Failure) AdaptiveSizePolicy::update_averages:  survived: 40475176  promoted: 40986832  overflow: false
AdaptiveSizeStart: 1.081 collection: 27 
  avg_survived_padded_avg: 120240512.000000  avg_promoted_padded_avg: 69725008.000000  avg_pretenured_padded_avg: 0.000000  tenuring_thresh: 1  target_size: 119013376
PSAdaptiveSizePolicy::compute_eden_space_size limits: desired_eden_size: 145719332 old_eden_size: 119537664 eden_limit: 119537664 cur_eden: 119537664 max_eden_size: 119537664 avg_young_live: 40456576
PSAdaptiveSizePolicy::compute_eden_space_size: costs minor_time: 0.277419 major_cost: 0.105898 mutator_cost: 0.616683 throughput_goal: 0.990000 live_space: 671297088 free_space: 472907776 old_eden_size: 119537664 desired_eden_size: 119537664
AdaptiveSizeStop: collection: 27 
 564812K->484899K(932352K), 0.0085535 secs]
1.098: [GC (Allocation Failure) AdaptiveSizePolicy::update_averages:  survived: 38675992  promoted: 36147912  overflow: false
AdaptiveSizeStart: 1.105 collection: 28 
  avg_survived_padded_avg: 116139840.000000  avg_promoted_padded_avg: 66457408.000000  avg_pretenured_padded_avg: 0.000000  tenuring_thresh: 1  target_size: 116391936
PSAdaptiveSizePolicy::compute_eden_space_size limits: desired_eden_size: 145949501 old_eden_size: 119537664 eden_limit: 119537664 cur_eden: 119537664 max_eden_size: 119537664 avg_young_live: 40278520
PSAdaptiveSizePolicy::compute_eden_space_size: costs minor_time: 0.286455 major_cost: 0.105898 mutator_cost: 0.607647 throughput_goal: 0.990000 live_space: 671119040 free_space: 472907776 old_eden_size: 119537664 desired_eden_size: 119537664
AdaptiveSizePolicy::survivor space sizes: collection: 28 (119013376, 119013376) -> (119013376, 116391936) 
AdaptiveSizeStop: collection: 28 
 601635K->518443K(934912K), 0.0076277 secs]

    6)查看熬过收集后剩余对象的年龄分布信息:

查看详情
# VM参数 -Xmx1g -Xms1g -XX:+PrintTenuringDistribution -Xloggc:d:\\gc\\gc.log
OpenJDK 64-Bit Server VM (25.382-b05) for windows-amd64 JRE (1.8.0_382-b05), built on Jul 14 2023 19:32:03 by "Administrator" with MS VC++ 12.0 (VS2013)
Memory: 4k page, physical 16595576k(6793364k free), swap 19085944k(5018192k free)
CommandLine flags: -XX:InitialHeapSize=1073741824 -XX:MaxHeapSize=1073741824 -XX:+PrintGC -XX:+PrintGCTimeStamps -XX:+PrintTenuringDistribution -XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX:-UseLargePagesIndividualAllocation -XX:+UseParallelGC 
0.251: [GC (Allocation Failure) 
Desired survivor size 44564480 bytes, new threshold 7 (max 15)
 262144K->77167K(1005056K), 0.0106601 secs]
0.297: [GC (Allocation Failure) 
Desired survivor size 44564480 bytes, new threshold 7 (max 15)
 339311K->148698K(1005056K), 0.0168431 secs]
0.349: [GC (Allocation Failure) 
Desired survivor size 44564480 bytes, new threshold 7 (max 15)
 410842K->220483K(1005056K), 0.0138825 secs]
0.400: [GC (Allocation Failure) 
Desired survivor size 44564480 bytes, new threshold 7 (max 15)
 482627K->295071K(1005056K), 0.0152177 secs]
0.454: [GC (Allocation Failure) 
Desired survivor size 119013376 bytes, new threshold 6 (max 15)
 557215K->367871K(1005056K), 0.0137273 secs]
0.502: [GC (Allocation Failure) 
Desired survivor size 119013376 bytes, new threshold 5 (max 15)
 630015K->440457K(859648K), 0.0135942 secs]
0.530: [GC (Allocation Failure) 
Desired survivor size 119013376 bytes, new threshold 4 (max 15)
 557193K->478072K(932352K), 0.0083706 secs]
0.553: [GC (Allocation Failure) 
Desired survivor size 119013376 bytes, new threshold 3 (max 15)
 594766K->510379K(932352K), 0.0109456 secs]
0.578: [GC (Allocation Failure) 
Desired survivor size 119013376 bytes, new threshold 2 (max 15)
 626730K->538179K(932352K), 0.0128859 secs]
0.606: [GC (Allocation Failure) 
Desired survivor size 119013376 bytes, new threshold 1 (max 15)
 654915K->565160K(932352K), 0.0141146 secs]
0.636: [GC (Allocation Failure) 
Desired survivor size 119013376 bytes, new threshold 1 (max 15)
 681896K->592366K(932352K), 0.0112850 secs]
0.661: [GC (Allocation Failure) 
Desired survivor size 119013376 bytes, new threshold 1 (max 15)
 709059K->627098K(932352K), 0.0075703 secs]
0.683: [GC (Allocation Failure) 
Desired survivor size 119013376 bytes, new threshold 1 (max 15)
 743834K->661328K(932352K), 0.0078308 secs]
0.691: [Full GC (Ergonomics)  661328K->334575K(932352K), 0.0424947 secs]
0.753: [GC (Allocation Failure) 
Desired survivor size 119013376 bytes, new threshold 1 (max 15)
 451311K->371579K(932352K), 0.0040235 secs]
0.772: [GC (Allocation Failure) 
Desired survivor size 119013376 bytes, new threshold 1 (max 15)
 488315K->404949K(932352K), 0.0071697 secs]
0.795: [GC (Allocation Failure) 
Desired survivor size 119013376 bytes, new threshold 1 (max 15)
 521684K->442605K(932352K), 0.0083711 secs]
0.819: [GC (Allocation Failure) 
Desired survivor size 119013376 bytes, new threshold 1 (max 15)
 559341K->478072K(932352K), 0.0079209 secs]
0.843: [GC (Allocation Failure) 
Desired survivor size 119013376 bytes, new threshold 1 (max 15)
 594808K->516113K(932352K), 0.0076133 secs]
0.867: [GC (Allocation Failure) 
Desired survivor size 119013376 bytes, new threshold 1 (max 15)
 632831K->545989K(932352K), 0.0082046 secs]
0.891: [GC (Allocation Failure) 
Desired survivor size 119013376 bytes, new threshold 1 (max 15)
 662442K->582484K(932352K), 0.0075331 secs]
0.913: [GC (Allocation Failure) 
Desired survivor size 119013376 bytes, new threshold 1 (max 15)
 699216K->615347K(932352K), 0.0073413 secs]
0.936: [GC (Allocation Failure) 
Desired survivor size 119013376 bytes, new threshold 1 (max 15)
 731863K->643803K(932352K), 0.0069251 secs]
0.959: [GC (Allocation Failure) 
Desired survivor size 119013376 bytes, new threshold 1 (max 15)
 760539K->678938K(932352K), 0.0074526 secs]
0.966: [Full GC (Ergonomics)  678938K->340322K(932352K), 0.0384871 secs]
1.026: [GC (Allocation Failure) 
Desired survivor size 119013376 bytes, new threshold 1 (max 15)
 457058K->379438K(932352K), 0.0039829 secs]
1.049: [GC (Allocation Failure) 
Desired survivor size 119013376 bytes, new threshold 1 (max 15)
 496174K->420106K(932352K), 0.0084216 secs]
1.077: [GC (Allocation Failure) 
Desired survivor size 113770496 bytes, new threshold 1 (max 15)
 536842K->459474K(937472K), 0.0090345 secs]
1.106: [GC (Allocation Failure) 
Desired survivor size 109051904 bytes, new threshold 1 (max 15)
 581298K->497005K(932352K), 0.0091583 secs]

# Java技术体系图


# main方法的执行过程

package com.howl.jvm;

/**
 * 0.类加载过程,首先获取类的二进制流,然后将类的方法代码,变量名,方法名,返回值等存储到方法区(元空间)。执行类里* 的static{}静态代码块代码,生成类的class对象,该对象会被存储到堆内存中。同时在常量池(元空间)中增加类的符号引用信* 息,代表类初始化完成。
 * 1.创建main线程,把main方法作为栈帧压入main线程,开始执行main方法
 * 2.(+/-表示可选分支)如果此时线程调度,会把当前线程所执行的字节码的行号指示器,也就是当前方法具体执行到了什么位置信息存储到程序* 计数器上,后续用这个计数器恢复线程。
 * 3.识别到了new关键字,创建A对象,执行步骤0,然后执行步骤4
 * 4.创建a对象,将对象加载到堆区(对象头以及实例属性)
 * 5.执行对象的test方法(将test方法作为栈帧压入当前线程栈区执行,执行完成后回到main栈帧)
 * 6.操作对象的实例属性(将该实例属性复制到当前线程的工作内存,也就是栈区),修改后再同步到主内存中(堆中对象的属性)。
 */
public class Test {
    public static void main(String[] args) {
        A a = new A();
		a.test();
		a.i=2;
    }
}

class A{
    private int i;
    public void test(){
        System.out.println("test");
    }

    public int getI() {
        return i;
    }

    public void setI(int i) {
        this.i = i;
    }
}

# 调优案例分析与实战

# 由Windows虚拟内存导致的长时间停顿

这个案例建议参考原论坛发文结合周老师的案例讲解一下看,原贴地址:FULL GC有可能导致JVM暂停1分钟以上吗? (opens new window)

# Safepoint导致长时间STW

这个案例来自小米,参见HBase实战:记一次Safepoint导致长时间STW的踩坑之旅 (opens new window)

# B站宕机事故复盘:2021.07.13 我们是这样崩的

这个宕机其实和Java和JVM都没什么关系了,不过B站这个复盘报告写的还可以,值得参考B站宕机事故复盘:2021.07.13 我们是这样崩的 (opens new window)

# jvm脑图