jvm 参数_JVM参数以及工具分析使用

首先,我们对于jvm的一些知识已经都有了一些了解。从内存结构到内存分配的策略,再到类的加载机制,然后就是对于垃圾回收机制的理解,虽然还有很多细节的地方我们不是很了解,但是细节不是一天两天就能完全记住了,要靠我们后面再实践中不断的总结和发现问题。所以我们现在就开始了解下jvm的一些工具的使用,方便我们对jvm进行优化。

JVM参数

首先还是先来看看jvm提供的一些参数,我们有对堆、栈的一些命令有简单的说到。这里我们先大概看一下常用的命令。

c49c9760dffc54b9d5fd5ad8466f2f56.png
常用jvm命令

这张图中就是我们常用的一些命令。下面简单的用一下。JVM 中最重要的一部分就是堆空间了,基本上大多数的线上 JVM 问题都是因为堆空间造成的 OutOfMemoryError。因此掌握 JVM 关于堆空间的参数配置对于排查线上问题非常重要。

堆配置

我们使用 -Xms 设置堆的初始空间大小,使用 -Xmx 设置堆的最大空间大小。

-Xms20M -Xmx20M -Xmn10M

在上面的命令中,我们设置 JVM 的初始堆大小为 20M,最大堆空间为 20M。然后-Xmn设置年轻代最大内存10M。

年轻代

堆分为年轻代和老年代。JVM 提供了参数 -Xmn 来设置年轻代内存的大小,但没有提供参数设置老年代的大小。但其实老年代的大小就等于堆大小减去年轻代大小。

-Xms20M -Xmx20M -Xmn10M -XX:+PrintGCDetails

上面的命令中,我们设置 JVM 堆初始大小为20M。其中年轻代的大小为 10M,那么剩下的就是老年代的大小,有 10M了。 我们可以给上述命令加上-XX:+PrintGCDetails 打印GC日志参数来查看内存区域的分配信息。

e9957d52417a58d858ffb9afc496412d.png

如上图所示,我们可以看到老年代的大小为 10M。

Eden区

在年轻代中,分为三个区域,分别是:eden 空间、from 空间、to 空间。如果要设置这部分的大小,那么就使用 -XX:SurvivorRatio 这个参数,该参数设置 eden / from 空间的比例关系,该参数的公式如下:

-XX:SurvivorRatio = eden/from = eden/to

例如我们的年轻代有 10 M,而我们设置 -XX:SurvivorRatio 参数为 2。也就是说 eden / from = eden / to = 2。这里教一个快速计算的方法,我们假设 eden = 2,那么 from = 1,to = 1,那么 eden + from + to = 10M。这样就可以算出每一份大小是 10/4 = 2.5M。所以 Eden 区 = 2.5 * 2 = 5M,from 区是 2.5 M,to 区是 2.5 M。

下面我们运行下命令来验证一下。

-Xms20m -Xmn10M -XX:SurvivorRatio=2 -XX:+PrintGCDetails

在上面的启动参数中,我们设置堆初始大小为 20M,年轻代大小为 10M,年轻代的 SurvivorRatio 比例为 2。那么最终分配的结果将会是:年轻代 10M,其中 Eden 区 5M、From 区 2.5M、To 区 2.5 M,老年代 10M。

3044fde8c61dde49ca287b42dbf1d13f.png

从上图可以看到:eden 空间是 5120 K,from 和 to 空间是 2560 K。

上图还有一个细节,即 PSYoungGen 这里的 total 只有 7680K,难道年轻代只有 7.5M 的内存吗?为什么不是 10M 呢?其实是因为这里的 total 指的是可用内存,from space 和 to space 两个区域,同一时间只有一个区域是可以用的。所以可用内存是 5120 + 2560 = 7680。

永久代

在 JDK 1.8 之前,所加载的类信息都放在永久代中。我们用 -XX:PermSize 设置永久代初始大小,用 -XX:MaxPermSize 设置永久代最大大小。

-XX:PermSize10m -XX:MaxPermSize50m -XX:+PrintGCDetails

在上面的启动参数中,我们设置永久代初始大小为 10M,最大大小为 50M。我们在 JDK1.7 的环境下运行上面的命令,会看到如下的 GC 日志。

3f9cbc210c8aeb263229c52b068f9301.png

在上图中,我们可以看到永久代的大小为我们设置的 10M。

栈空间

栈空间是每个线程各自有的一块区域,如果栈空间太小,也会导致 StackOverFlow 异常。而要设置栈空间大小,只需要使用 -Xss 参数就可以。

-Xss2m

上面的启动命令设置最大栈空间为 2M。

打印显式参数 -XX:+PrintVMOptions

该参数表示程序运行时,打印虚拟机接受到的命令行显式参数。我们用下面的命令运行程序:

-XX:+UseSerialGC -XX:+PrintVMOptions

输出结果:

Hello World
Disconnected from the target VM, address: '127.0.0.1:26670', transport: 'socket'
VM option '+UseSerialGC'
VM option '+PrintVMOptions'

可以看到我们设置了+UseSerialGC+PrintVMOptions两个参数,最后运行时也将这两个参数打印出来了。

JVM参数之GC日志配置

说到 Java 虚拟机,不得不提的就是 Java 虚拟机的 GC(Garbage Collection)日志。而对于 GC 日志,我们不仅要学会看懂,而且要学会如何设置对应的 GC 日志参数。今天就让我们来学习一下 Java 虚拟机中所有与 GC 日志有关的参数。相信掌握了这些参数之后,对于大家线上打印 GC 日志是有不少帮助的。

为了能够更直观地显示出每个参数的作用,我们将以下面的 Demo 为例子去设置 GC 日志参数。

public class GCDemo {
    public static void main(String[] args) {
        // allocate 4M space
        byte[] b = new byte[4 * 1024 * 1024];
        System.out.println("first allocate");
        // allocate 4M space
        b = new byte[4 * 1024 * 1024];
        System.out.println("second allocate");
    }
}

在上面的程序中,我们两次分配了 4M 的内存空间。为了认为制造 GC,我们启动时的 JVM 参数固定加上下面几个参数:

-XX:+UseSerialGC -Xms20M -Xmx20M -Xmn10M -XX:SurvivorRatio=8
  • -XX:+UseSerialGC 表示强制使用Serial+SerialOld收集器组合
  • -Xms20m 表示堆空间初始大小为 20 M。
  • -Xmx20m 表示堆空间最大大小为 20 M。
  • -Xmn10m 表示新生代大小为 10M。
  • -XX:SurvivorRatio=8 表示Eden:Survivor=8:1

经过上面这个设置,此时我们的堆空间的内存比例情况如下:Eden区 8M,FromSurvivor 1M,ToSurvivor 1M,老年代 10M。

下面就让我们来看看油管 GC 的参数有哪些吧。

打印GC日志

在 GC 日志参数中,最简单的一个参数就是打印 GC 日志:-XX:PrintGC。我们用下面的命令运行程序:

-XX:+UseSerialGC -Xms20M -Xmx20M -Xmn10M -XX:SurvivorRatio=8 -XX:+PrintGC

输出结果:

first allocate
[GC (Allocation Failure)  6659K->4799K(19456K), 0.0024150 secs]
second allocate

可以看到程序在第一次分配数组空间的时候发生了 GC,并且把 GC 前后以及堆空间大小都打印了出来。该日志显示 GC 前堆空间使用量为 6659K(4M左右)。GC 后堆空间为 4799K,当前可用堆大小为 19456K。

但你会发现使用 PrintGC 参数打印出来的日志比较简单,无法查看更详细的信息。如果你要查看更详细的信息,那么就需要下面这个参数。

打印详细GC日志

如果要查看更加详细的 GC 日志,那么就要使用 -XX:+PrintGCDetails参数。下面我们使用该参数运行程序:

-XX:+UseSerialGC -Xms20M -Xmx20M -Xmn10M -XX:SurvivorRatio=8 -XX:+PrintGCDetails

程序输出:

first allocate
second allocate
[GC (Allocation Failure) [DefNew: 6659K->703K(9216K), 0.0025789 secs] 6659K->4799K(19456K), 0.0026131 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
Heap
 def new generation   total 9216K, used 5039K [0x00000000fec00000, 0x00000000ff600000, 0x00000000ff600000)
  eden space 8192K,  52% used [0x00000000fec00000, 0x00000000ff03c018, 0x00000000ff400000)
  from space 1024K,  68% used [0x00000000ff500000, 0x00000000ff5afc40, 0x00000000ff600000)
  to   space 1024K,   0% used [0x00000000ff400000, 0x00000000ff400000, 0x00000000ff500000)
 tenured generation   total 10240K, used 4096K [0x00000000ff600000, 0x0000000100000000, 0x0000000100000000)
   the space 10240K,  40% used [0x00000000ff600000, 0x00000000ffa00010, 0x00000000ffa00200, 0x0000000100000000)
 Metaspace       used 3327K, capacity 4556K, committed 4864K, reserved 1056768K
  class space    used 359K, capacity 392K, committed 512K, reserved 1048576K

从上面的日志可以看出,该参数能打印出更加详细的 GC 信息,包括:年轻代的信息、永久代的信息。

[GC (Allocation Failure) [DefNew: 6659K->703K(9216K), 0.0025789 secs] 6659K->4799K(19456K), 0.0026131 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]

该参数还会在退出之前打印出整个堆的详细信息:

Heap
 def new generation   total 9216K, used 5039K [0x00000000fec00000, 0x00000000ff600000, 0x00000000ff600000)
  eden space 8192K,  52% used [0x00000000fec00000, 0x00000000ff03c018, 0x00000000ff400000)
  from space 1024K,  68% used [0x00000000ff500000, 0x00000000ff5afc40, 0x00000000ff600000)
  to   space 1024K,   0% used [0x00000000ff400000, 0x00000000ff400000, 0x00000000ff500000)
 tenured generation   total 10240K, used 4096K [0x00000000ff600000, 0x0000000100000000, 0x0000000100000000)
   the space 10240K,  40% used [0x00000000ff600000, 0x00000000ffa00010, 0x00000000ffa00200, 0x0000000100000000)
 Metaspace       used 3327K, capacity 4556K, committed 4864K, reserved 1056768K
  class space    used 359K, capacity 392K, committed 512K, reserved 1048576K

GC前后打印堆信息

上面两个命令基本上可以应付 90% 的使用场景了,但有时候我们在 GC 前后还想获取更加详细的信息。那么我们可以使用 PrintHeapAtGC 参数,该参数会在 GC 前后打印堆信息。

使用下面的命令运行程序:

-XX:+UseSerialGC -Xms20M -Xmx20M -Xmn10M -XX:SurvivorRatio=8 -XX:+PrintHeapAtGC

输出结果:

first allocate
{Heap before GC invocations=0 (full 0):
 def new generation   total 9216K, used 6659K [0x00000000fec00000, 0x00000000ff600000, 0x00000000ff600000)
  eden space 8192K,  81% used [0x00000000fec00000, 0x00000000ff280f90, 0x00000000ff400000)
  from space 1024K,   0% used [0x00000000ff400000, 0x00000000ff400000, 0x00000000ff500000)
  to   space 1024K,   0% used [0x00000000ff500000, 0x00000000ff500000, 0x00000000ff600000)
 tenured generation   total 10240K, used 0K [0x00000000ff600000, 0x0000000100000000, 0x0000000100000000)
   the space 10240K,   0% used [0x00000000ff600000, 0x00000000ff600000, 0x00000000ff600200, 0x0000000100000000)
 Metaspace       used 3310K, capacity 4556K, committed 4864K, reserved 1056768K
  class space    used 358K, capacity 392K, committed 512K, reserved 1048576K
Heap after GC invocations=1 (full 0):
 def new generation   total 9216K, used 702K [0x00000000fec00000, 0x00000000ff600000, 0x00000000ff600000)
  eden space 8192K,   0% used [0x00000000fec00000, 0x00000000fec00000, 0x00000000ff400000)
  from space 1024K,  68% used [0x00000000ff500000, 0x00000000ff5afbd0, 0x00000000ff600000)
  to   space 1024K,   0% used [0x00000000ff400000, 0x00000000ff400000, 0x00000000ff500000)
 tenured generation   total 10240K, used 4096K [0x00000000ff600000, 0x0000000100000000, 0x0000000100000000)
   the space 10240K,  40% used [0x00000000ff600000, 0x00000000ffa00010, 0x00000000ffa00200, 0x0000000100000000)
 Metaspace       used 3310K, capacity 4556K, committed 4864K, reserved 1056768K
  class space    used 358K, capacity 392K, committed 512K, reserved 1048576K
}
second allocate

仔细看一下,会发现在 GC 发生前后都打印了一次堆空间信息。

9b232a956203535cbb3b7f8e81dc22ee.png

通过这个参数,我们可以详细了解每次 GC 时堆空间的详细信息。

打印GC发生的时间 -XX:+PrintGCTimeStamps

这个参数非常简单,就是在每次 GC 日志的前面加上一个时间戳。这个时间戳表示 JVM 启动后到现在所逝去的时间。

使用下面的参数运行程序:

java -XX:+UseSerialGC -Xms20M -Xmx20M -Xmn10M -XX:SurvivorRatio=8 -XX:+PrintGC -XX:+PrintGCTimeStamps com.chenshuyi.GCDemo

输出结果:

first allocate
second allocate
0.130: [GC (Allocation Failure)  4767K->4374K(19456K), 0.0051351 secs]

上面日志第 3 行中的「0.130」就是该 GC 发生的时间。

-XX:+PrintGCApplicationConcurrentTime 打印应用程序的执行时间

使用下面的命令运行程序:

-XX:+UseSerialGC -Xms20M -Xmx20M -Xmn10M -XX:SurvivorRatio=8 -XX:+PrintGC -XX:+PrintGCApplicationConcurrentTime

运行结果:

Application time: 0.0000283 seconds
Application time: 0.0570958 seconds
Application time: 0.0004787 seconds
first allocate
Application time: 0.0029640 seconds
[GC (Allocation Failure)  6659K->4799K(19456K), 0.0025556 secs]
second allocate
Application time: 0.0010957 seconds

-XX:+PrintGCApplicationStoppedTime 打印应用由于GC而产生的停顿时间

使用下面的命令运行程序:

-XX:+UseSerialGC -Xms20M -Xmx20M -Xmn10M -XX:SurvivorRatio=8 -XX:+PrintGC -XX:+PrintGCApplicationStoppedTime

运行结果:

first allocate
second allocate
[GC (Allocation Failure)  4767K->4374K(19456K), 0.0045644 secs]
Total time for which application threads were stopped: 0.0047873 seconds, Stopping threads took: 0.0000329 seconds

可以看到最后一行打印出了因为 GC 而暂停的时间。

保存GC日志 -Xloggc

这个参数可以将 GC 日志输出到文件中保存起来。-XX:+PrintReferenceGC参数可以记录回收了多少不同引用类型的引用。

使用下面的参数运行程序:

-XX:+UseSerialGC -Xms20M -Xmx20M -Xmn10M -XX:SurvivorRatio=8 -XX:+PrintGC -XX:+PrintReferenceGC -Xloggc:gc.log

运行之后在本目录会生成一个 gc.log 文件,打开该文件:

Java HotSpot(TM) 64-Bit Server VM (25.181-b13) for bsd-amd64 JRE (1.8.0_181-b13), built on Jul  7 2018 01:02:31 by "java_re" with gcc 4.2.1 (Based on Apple Inc. build 5658) (LLVM build 2336.11.00)
Memory: 4k page, physical 8388608k(45132k free)

/proc/meminfo:

CommandLine flags: -XX:InitialHeapSize=20971520 -XX:MaxHeapSize=20971520 -XX:MaxNewSize=10485760 -XX:NewSize=10485760 -XX:+PrintGC -XX:+PrintGCTimeStamps -XX:+PrintReferenceGC -XX:SurvivorRatio=8 -XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX:+UseSerialGC 
0.124: [GC (Allocation Failure)  4767K->4374K(19456K), 0.0047748 secs]

可以看到堆的相关信息,以及 GC 的信息。

最后用列表的形式总结一下,加深一下印象。

b808e1a4573197fe0d5d0aab9e342bf5.png

常用工具

查看虚拟机进程:jps 命令

jps 命令可以列出所有的 Java 进程。如果 jps 不加任何参数,可以列出 Java 程序的进程 ID 以及 Main 函数短名称,如下所示。

$ jps
6540 Jps
64447 Main

除此之外,还可以指定下面的参数自定义输出信息:

22803a18ceb3dc8b8fdb7bd63e1aaa67.png

虚拟机统计信息:jstat 命令

jstat 用于观察 Java 堆信息的详细情况,其基本使用语法位:

jstat -<option> [-t] [-h<lines>] <vmid> [<interval>] [<count>]]

其中 option 可以由以下值构成。

b24b6b51822914e81434bb0332172764.png

-t 参数表示输出时间戳、-h 参数表示在多少行后输出一个表头、vmid 则是虚拟机的进程ID、interval 和 count 表示输出间隔以及输出次数。

例如:我们用jstat命令来查看一个8644的JVM进程的gc信息。

jstat -gc 8644 1000 10

4f1c670aafe8c2eadf3d3bcf2be20b88.png

查看虚拟机参数:jinfo 命令

jinfo 可以用来查看正在运行的 Java 应用程序的扩展参数,甚至支持在运行时,修改部分参数。它的基本语法是:

jinfo <option> <pid>

执行例子,查询 MaxHeapSize 参数值

C:Users1002360>jinfo -flag MaxHeapSize 8644
-XX:MaxHeapSize=4280287232

查看线程堆栈:jstack 命令

jstack 命令用于导出 Java 应用程序的线程堆栈。jstack命令格式:

jstack [option] vmid

下面使用jstack查看一个线程堆栈的例子:

8a9d43befd47ac0da35d0b32cc3b5921.png

使用jstack排查死锁

demo:

//运行主类
public class DeadLockDemo {
    public static void main(String[] args) {
        DeadLock d1 = new DeadLock(true);
        DeadLock2 d2 = new DeadLock2(true);
        Thread t1 = new Thread(d1);
        Thread t2 = new Thread(d2);
        t1.start();
        t2.start();
    }
}

//定义锁对象
class MyLock {
    public static Object obj1 = new Object();
    public static Object obj2 = new Object();
}

//死锁代码
class DeadLock implements Runnable {
    private boolean flag;

    DeadLock(boolean flag) {
        this.flag = flag;
    }

    public void run() {
        if (flag) {
            while (true) {
                synchronized (MyLock.obj1) {
                    System.out.println(Thread.currentThread().getName() + "----if获得obj1锁");
                    synchronized (MyLock.obj2) {
                        System.out.println(Thread.currentThread().getName() + "----if获得obj2锁");
                    }
                }
            }
        }
    }
}

class DeadLock2 implements Runnable {
    private boolean flag;

    DeadLock2(boolean flag) {
        this.flag = flag;
    }

    public void run() {
        if (flag) {
            while (true) {
                synchronized (MyLock.obj2) {
                    System.out.println(Thread.currentThread().getName() + "----if获得obj1锁");
                    synchronized (MyLock.obj1) {
                        System.out.println(Thread.currentThread().getName() + "----if获得obj2锁");
                    }
                }
            }
        }
    }
}

拉到最后发现:

dc148e0a6259d2ac4c408653b4395fca.png

导出堆到文件:jmap 命令

jmap 是一个多功能命令,可以生成 Java 程序的 Dump 文件,也可以查看堆内对象实例的统计信息、查看 ClassLoader 的信息以及 finalizer 队列。

jmap [option] vmid

打印堆内存信息

-XX:+PrintFlagsFinal -Xms300M -Xmx300M
jmap -heap PID

da999d13c5beaea0d34610386b204611.png

dump出堆内存相关信息:

jmap -dump:format=b,file=heap.hprof PID

c6fa422d807f970a31b16ac1eec02438.png

要是在发生堆内存溢出的时候,能自动dump出该日志就好了。所以一般在开发中,JVM参数可以加上两句配置,这样在堆内存溢出的时候,会自动dump出该文件。

-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=D:/heap.hprof

HeapDumpOnOutOfMemoryError 参数表示当JVM发生OOM时,自动生成DUMP文件。

HeapDumpPath 表示dump文件路径。

关于dump下来的文件,我们需要结合工具进行分析,这块我们后面会说到使用哪些诶工具。

常用分析工具

jconsole

JConsole工具是JDK自带的可视化监控工具。查看java应用程序的运行概况、监控堆信息、永久区使用情况、类加载情况等。

b82576bc1729301f50f43599fff8843e.png
例如可以直接检测死锁

jvisualvm

是jvm自带的工具,可以直接拿到线程dump信息。

92e2646aab15786f3bbb1498b2aba002.png
监控本地java进程:可以直接打开检测到本地进程
监控远程java进程:本机的VisualVM就必须和远程的JVM要进行通信, Visualvm目前支持两种remote connection方式,分别是jstatd和JMX方式。远程监控某个中间件时,需要修改中间件的启动文件,添加上关于jmx等的信息。

Arthas

Arthas 是 Alibaba 在 2018 年 9 月开源的 Java 诊断工具。支持 JDK6+, 采用命令行交互模式,提供 Tab 自动不全,可以方便的定位和诊断线上程序运行问题。

得益于 Arthas 强大且丰富的功能,让 Arthas 能做的事情超乎想象。下面仅仅列举几项常见的使用情况,更多的使用场景可以在熟悉了 Arthas 之后自行探索。

是否有一个全局视角来查看系统的运行状况?
为什么 CPU 又升高了,到底是哪里占用了 CPU ?
运行的多线程有死锁吗?有阻塞吗?
程序运行耗时很长,是哪里耗时比较长呢?如何监测呢?
这个类从哪个 jar 包加载的?为什么会报各种类相关的 Exception?
我改的代码为什么没有执行到?难道是我没 commit?分支搞错了?
遇到问题无法在线上 debug,难道只能通过加日志再重新发布吗?
有什么办法可以监控到 JVM 的实时运行状态?
  • 安装

可以在官方 Github 上进行下载,如果速度较慢,可以尝试国内的码云 Gitee 下载。

# github下载
wget https:// alibaba.github.io/artha s/arthas-boot.jar
  • 打印帮助信息

java -jar arthas-boot.jar -h

  • 运行

Arthas 只是一个 java 程序,所以可以直接用 java -jar 运行。运行时或者运行之后要选择要监测的 Java 进程。

# 运行方式1,先运行,在选择 Java 进程 PID
java -jar arthas-boot.jar
# 运行方式2,运行时选择 Java 进程 PID
java -jar arthas-boot.jar [PID]

查看 PID 的方式可以通过 ps 命令,也可以通过 JDK 提供的 jps命令。

  • 常用命令:

3fecd7fade9a10898148c7da7d538394.png

MAT

Java堆分析器,用于查找内存泄漏。Heap Dump,称为堆转储文件,是Java进程在某个时间内的快照。

  • dump文件包含的内容:
1,全部的对象:类,域,原生值和引用;
2,全部的类:classloader,类名,超类,静态域;
3,GC root:被JVM定义的可触达的对象;
4,线程栈和本地变量:线程的call stack,本地对象每帧的信息。
  • 获取dump文件,可以通过jmap获取,或者jvisualvm工具获取。
  • 使用

先写一段内存泄露直到溢出代码并运行

/**
 * 内存泄露直到溢出
 */
public class DumpDemo {
    private static final int _1MB = 1024 * 1024;
    public static void main(String[] args) {
        System.out.println("-------------mytime----------------");
        Map<String,Object> m = new HashMap<>();
        int i = 0;
        do{
            byte[] test = new byte[_1MB];
            m.put(String.valueOf(i), test);
            i++;
        }while(i<100000);
    }
}

3868940d62e17b2cf2b25c4b2d417f2e.png

把dump文件弄下来后导入到MAT中进行分析。

8f1e026c4c56674e26afe158a09f820c.png

具体的使用可以进行百度。常用功能:

Histogram

Histogram可以列出内存中的对象,对象的个数及其大小
Class Name:类名称,java类名Objects:类的对象的数量,这个对象被创建了多少个
Shallow Heap:一个对象内存的消耗大小,不包含对其他对象的引用
Retained Heap:是shallow Heap的总和,即该对象被GC之后所能回收到内存的总和
功能:
1:右击类名--->List Objects--->with incoming references--->列出该类的实例
2:右击Java对象名--->Merge Shortest Paths to GC Roots--->exclude all ...--->找到GCRoot以及原因

Leak Suspects

查找并分析内存泄漏的可能原因
使用方式:Reports--->Leak Suspects--->Detail

Top Consumers

列出大对象

GC日志分析工具

要想分析日志的信息,得先拿到GC日志文件才行,所以得先配置一下根据前面参数的学习。下面的配置很容易看懂

-XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+PrintGCDateStamps-Xloggc:gc.log
  • 在线分析
http://gceasy.io
  • GCViewer工具
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值