一文了解JVM整体设计

news2024/11/24 0:23:05

  • 一、JDK / JRE / JVM
  • 二、.Java 文件运行过程
  • 三、JVM运行时数据区
    • 3.1 Method Area
    • 3.2 Heap
    • 3.3 Java Virtual Machine Stacks
    • 3.4 Native Method Stacks
    • 3.5 The PC Register
  • 四、JVM内存模型
    • 4.1 JVM对象创建和回收过程
  • 五、垃圾收集
    • 5.1 确定垃圾收集对象
      • 5.1.1 引用计数法
      • 5.1.2 可达性分析
    • 5.2 垃圾收集算法
      • 5.2.1 标记-清除
      • 5.2.2 标记-整理
      • 5.2.3 标记-复制
    • 5.3 JVM不同区垃圾回收算法选择
  • 六、垃圾收集器
    • 6.1 Serial
    • 6.2 Parallel
    • 6.3 CMS(ConcMarkSweepGC)
    • 6.4 G1(Garbage-First)
    • 6.5 ZGC(The Z Garbage Collector)
    • 6.6 垃圾收集器分类
    • 6.7 垃圾收集器参数
    • 6.8 Reponsiveness and throughput
    • 6.9 垃圾收集发生时机
  • 七、JVM调优
    • 7.1 参数调优
    • 7.1 参数查看
  • 八、常用工具
    • 8.1 JDK常用工具
    • 8.2 第三方通用工具 - Arthas
    • 8.3 内存分析工具
    • 8.4 GC分析工具

一、JDK / JRE / JVM

作为一个 Java 开发人员,你肯定听说过JDK、JRE、JVM,那么这三者是否存在什么关系与区别呢?

JDK 是整改 JAVA SE 的核心,其中包括了 Java 运行环境、Java 编译工具(javac)、Java 打包工具(jar.exe) 和 Java 基础类库,还包括了 JRE。JDK 安装目录如下:
在这里插入图片描述
其中真正在 Java 运行时发挥作用的是 bin、include、lib、 jre这四个目录。

  • bin:存放了 JDK 的各种工具命令,如 javac、java
  • include:存放了一些平台特定的头文件
  • lib:类库
  • jre:java运行时环境

JRE,Java 运行环境,包含 JVM 标准实现(JVM虚拟机)与 Java 核心类库。

JVM,Java 虚拟机,是 Java 运行时的环境。

三者关系如下:

在这里插入图片描述

二、.Java 文件运行过程

在日常 Java 开发过程中,从代码编写到运行,步骤如下:

  1. 第一步我们会创建一个 .java 后缀的文件,在其编写对应的逻辑代码。
// HelloWorld.java 代码
public class HelloWorld {

    public static void main(String[] args) {
        System.out.println("Hello world!!!!!");
    }
}
  1. 第二步如果不使用开发工具,我们需通过 javac 对其编译,生成一个 .class 文件。
javac HelloWorld.java
  1. 最后,通过 java 命令将 .class 文件交由 JVM 运行。
java HelloWorld

整体过程如下:
在这里插入图片描述
javac 命令会将其 .java 文件编译成 .class 文件,那么 java HelloWorld 命令将其 .class 交由 JVM 运行,期间做了哪些动作呢?如下:

  1. 装载:通过类加载器(ClassLoader)扫描所有需要运行的 .class 文件,将其 .class 文件转换为字节码交由 JVM 存储。
  2. 链接
    2.1 校验:校验 .class 类信息是否符合 JVM 规范,如是否以 CA FE BA BE 开头等
    2.2 准备:为类中的静态变量分配内存空间,并将其初始化为默认值,如:类中存在 static int i = 10 类的成员属性,经过该步骤后,会变为 static init i = 0
    2.3 解析:将类的符号引用转变为直接引用。这句话非常抽象,辣么什么是符号引用、直接引用? 符号引用:是一组用来描述所引用的目标的符号,符号可以是任何形式的字面量,只要使用时能够无歧义的定位到目标即可,简单来说就是一组描述目标的符号。 直接引用:指向目标的指针,通过直接引用,JVM 可以知道引用类的实际内存地址。
  3. 初始化:对类的静态变量、静态代码块执行初始化操作

三、JVM运行时数据区

在这里插入图片描述
用一句话来总结这五个区的作用及关系:JAVA 通过类加载机制,将 .class 文件信息、常量等存放在 Method Area(方法区),程序在运行时,创建 Bean 对象,存放在 Heap(堆)中,线程在运行时,通过Java虚拟机栈记录方法的调用关系,在线程运行时,通过 Native Method Stacks(本地方法栈)记录 Native 方法调用状态,当CPU进行时间片切换调度时,通过 The PC Register(程序计数器) 记录正在执行的Java虚拟机字节码指令地址。

下面详细说明一下这五个区的作用。

3.1 Method Area

方法区是各个线程共享的内存区域,在虚拟机启动时创建,用于存储被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据,一般我们也将方法区叫做非堆。

注意:当方法区无法满足内存分配需求时,将抛出 OOM(OutOfMemoryError) 异常。

3.2 Heap

Java 堆是 Java 虚拟机所管理内存中最大的一块,在虚拟机启动时创建,被所有线程共享,用于存储程序运行时实例对象。

注意:当堆内存空间不足时,也会抛出 OOM(OutOfMemoryError) 异常。

3.3 Java Virtual Machine Stacks

Java 虚拟机栈是一个用于保存线程运行状态的区域,所以 Java 虚拟机栈是线程私有的,随着线程的创建而创建

每一个被线程执行的方法,为该栈中的栈帧,即每个方法对应一个栈帧。调用一个方法,就会向栈中压入一个 栈帧;一个方法调用完成,就会把该栈帧从栈中弹出。如下:

  1. 代码
public class Test {

    public static void main(String[] args) {
        aMethod();
    }

    private static void aMethod() {
        bMethod();
        cMethod();
    }

    private static void bMethod() {}
    private static void cMethod() {}
}
  1. Java虚拟机栈
    在这里插入图片描述

3.4 Native Method Stacks

本地方法栈是用于记录线程中调用 Native 方法运行状态的区域,结构同 Java Virtual Machine Stacks 类似。

3.5 The PC Register

程序计数器用于记录正在执行的 Java 虚拟机字节码指令地址,是线程私有的,随着线程的创建而创建,是当 CPU 进行线程上下文切换时,会通过程序计数器记录当前线程执行指令地址。

注意:如果线程正在执行Java方法,则计数器记录的是正在执行的虚拟机字节码指令的地址。如果正在执行的是Native方法,则这个计数器为空。

四、JVM内存模型

上面对 JVM 运行时数据区做了详细描述,其中 Java虚拟机栈、本地方法栈、程序计数器都是线程私有的,而用于存储数据的方法区(也叫非堆)和堆是线程共享的。所以 JVM内存主要涉及 方法区 和 堆,下面对这两大块进行详细描述。

JVM将其内存分为两大块,一块是方法区(Method Areas,也叫非堆),另外一快是堆(Heap)。整体模型如下:
在这里插入图片描述
方法区(Method Areas):用于存储类对象(.class)、常量、静态变量、即时编译器编译后的代码信息等。

堆(Heap):用于存储运行时实例对象。其中 堆(Heap) 又分为 Young区(年轻代) 和 Old区(年老代),用于存储不同生命周期的实例对象,其中,Young区 用于存储生命周期较短的瞬时对象,Old区 用于存储生命周期长 和 某些大对象,当 Young区 的对象存活较长后,会放入 Old 区进行存储(默认是15次垃圾回收后,可通过参数 -XX:MaxTenuringThreshold=N 指定最大年龄),其次,当对象超过一定字节大小后,也会直接叫由 Old 区进行存储(可通过参数 --XX:PretenureSizeThreshold=3145728 设置,单位是 byte,此处表示 3MB)。
默认情况下,Young(新生代) 和 Old(老年代) 的比值是 1:2 分配,可以通过参数 -XXNewRatio=2 来指定,如下:

# 新生代:老年代=1:2
-XX:NewRatio=2

# 新生代:老年代=1:4
-XX:NewRatio=4

而在 JVM 中,为了更好的管理 Young区 的内存空间,又将 Young区 分为了 Eden区 和 Survivor区。

Eden区:用于存储线程运行创建的对象,不过大多数对象都是“朝生夕死”,存活时间非常短。

Survivor区:用于存储 Eden区 发生垃圾回收后,存活下来的对象。并且 Survivo区 内部还划分为了 S0 和 S1 区(也称为From、To区),在同一个时间点上,S0 和 S1 只能有一个区有数据,另一个是空的。

Oracle JVM 官网描述 Eden区 和 Survivor区 的S0、S1 空间默认所占的比例是 8:1:1,可以通过 -XX:SurvivorRatio=8 调整这个空间的比例,如下:

# Eden:S0:S1=8:1:1(默认)
-XX:SurvivorRatio=8

# Eden:S0:S1=6:1:1
-XX:SurvivorRatio=6

JVM 将其内存这样分配的主要目的最大的利用内存空间,并且保证其内存空间的连续性。

4.1 JVM对象创建和回收过程

JVM 将内存划分为多个可用区域,用于对象创建时内存的分配,主要步骤如下:

  1. 大多数对象的创建一般会优先在 Eden区 分配内存空间进行存储,当 Eden区 内存不足时,会发生 Minor GC(也叫Young GC)。
  2. Minor GC 会回收掉 Eden区、Survivor区 中的垃圾对象,并且将 Eden区 以及 Survivor区(假设为S0) 中存活的对复制到 Survivor区 中的 S1 区中,然后清除 Eden区 和 Survivor区 中标记为垃圾的对象,重复此操作。
  3. 如果 Eden区、Survivor区内存分配不足,会将对象放入 Old区 进行存储。
  4. 如果 Old区 内存不足,会先进行一次 Major GC 或者 Full GC,然后再次判断 Old区 是否存在可分配内存。
  5. 当发送 Full GC 后,Old 区还是无可分配内存,JVM就会抛出 OOM(OutOfMemoryError) 异常。

通过以上的内存分配机制,保证了 JVM Young区内存空间的最大利用率以及内存空间的连续性。

注意:因为 Young区 的对象大多数都是"朝生夕死"的,一般来说Eden:S0:S1=8:1:1 是较为合理的,假如是 6:2:2 的话,就会浪费20%的 Young区 内存,并且 Eden区 只有60%,这样会导致较为频繁的 Young GC。

流程图:
在这里插入图片描述

五、垃圾收集

Java 程序在运行是会不断创建新的对象,存放在 Young区、Old区,内存的空间是有限的,所以需要一定的算法,来进行内存的回收。在JVM中,那些对象才是需要被回收的呢?

  1. 首选,需要确定哪些对象需要被回收
  2. 然后,通过一定算法,进行垃圾回收

5.1 确定垃圾收集对象

5.1.1 引用计数法

对于某个对象而言,只要应用程序中持有该对象的引用,就说明该对象不是垃圾,如果一个对象没有任何指针对其引用,它就是垃圾。

  1. 判断当前对象引用数量是否为0,如果为0,则可进行垃圾回收
  2. 每个对象都存在一个引用计算器,被引用则+1,完成引用则-1

优点:执行效率高,程序执行受影响较小
缺点:无法检测出循环引用的情况,会导致 OOM

5.1.2 可达性分析

通过 GC Root 判断对象的引用是否可达来判断对象是否可回收,不可达,则可以尝试进行垃圾回收。

那么, 那些对象能够作为 GC Root 呢?

  • JVM虚拟机栈的本地变量表
  • static成员变量
  • 常量引用
  • 活跃线程
  • 本地方法栈的变量

如下:
在这里插入图片描述
其中,obj7、obj8、obj9 无 GC Root 直接关联,所有判断为垃圾对象。

由于引用计数法存在OOM的缺点,JVM内部采用可达性分析,来判断当前对象是否可进行垃圾回收。

5.2 垃圾收集算法

JVM 通过可达性分析来判断哪些对象需要进行垃圾回收后,则需要根据不同场景选用不同算法进行垃圾回收,常用的垃圾回收算法有:

  • 标记-清除
  • 标记-整理
  • 标记-复制

5.2.1 标记-清除

  • 标记:通过可达性分析,找出内存中需要回收的对象,并进行标记。
  • 清除:清除被标记的需要回收的对象,释放对应内存空间。
    在这里插入图片描述
    缺点:
    1. 执行效率会随着堆的增加而降低,标记需要遍历整个堆,且如果有大量对象都需要被回收,清除的效率也会很低。
    2. 产生大量空间碎片。大量的空间碎片会导致在分配大java对象时没有足够的内存空间,进而提前引发一次垃圾回收。

5.2.2 标记-整理

  • 标记:通过可达性分析,找出内存中需要回收的对象,并进行标记。
  • 整理:让所有存活对象向内存的一端移动,然后直接清除掉边界以外的全部区域。
    在这里插入图片描述
    标记-整理 算法解决了 标记-清除 内存碎片问题

5.2.3 标记-复制

  • 标记:通过可达性分析,找出内存中需要回收的对象,并进行标记。
  • 复制:将一个区域的内存还存活的对象复制到另一个相同大小的内存区域,然后对其内存一次性全部清除
    在这里插入图片描述
    标记-复制 算法是典型的以空间换时间,解决了 标记-清除 内存碎片问题、大量对象可回收清除时的效率问题。

5.3 JVM不同区垃圾回收算法选择

  • Young区:标记-清除,标记-复制(通过S0、S1进行复制)
  • Old去:标记-清除,标记整理

六、垃圾收集器

什么是垃圾收集器?
垃圾收集器是对不同垃圾回收算法的一种具体实现。

6.1 Serial

串行收集器,通过使用一个线程执行所有垃圾回收工作。

  • Serial 收集器可以用于新老年代
  • 新生代:采用标记-复制算法
  • 老年代:采用标记-整理算法

在这里插入图片描述

6.2 Parallel

并行收集器,也被称为吞吐量收集器,它是一种类似于串行收集器的分代收集器。
串行和并行收集器之间的主要区别是并行收集器具有多个线程,用于加速垃圾收集。

  • Parallel 收集器可以用于新老年代
  • 新生代:采用标记-复制算法
  • 老年代:采用标记-整理算法

在这里插入图片描述

6.3 CMS(ConcMarkSweepGC)

英文全名Concurrent Mark Sweep,并发标记扫描(CMS)收集器,也称为并发低暂停收集器,它试图通过与应用程序线程并发执行大多数垃圾收集工作,以此来最小化由于垃圾收集造成的主线程暂停。

  • CMS 只可用于老年代
  • 老生代:采用标记-清除算法
    在这里插入图片描述
    运行步骤如下:
  1. 初始标记:标记 GC Root 直接关联对象,暂停时间的持续时间通常较短
  2. 并发标记:在Java应用程序线程执行时,并发的遍历 GC Root 下所有可达对象。
  3. 重新标记:备注查找由于在Java应用程序线程并发收集器完成跟踪对象后,对对象进行更新而在并发标记阶段遗漏的对象,简单来说,就是并发标记因用户程序变动的内容。
  4. 并发清理:并发扫描并清除不可达对象,进行内存空间回收。

在并发时产生的新的垃圾,称为浮动垃圾,交由下次清理。

6.4 G1(Garbage-First)

G1是一个并发收集器,其工作原理主要是优先回收垃圾最多的Region区域。通过 G1 可以满足高概率暂停时间目标的能力,同时实现高吞吐量。

什么是 Region区?

使用G1收集器时,Java 堆的内存布局与就与其他收集器有很大差别,它将整个 Java 堆划分为多个大小相等的独立区域(Region),虽然还保留有
新生代和老年代的概念,但新生代和老年代不再是物理隔离的了,它们都是一部分 Region(不需要连续)的集合。如下:
在这里插入图片描述
每个 Region 大小都是一样的,可以是 1M~32M 之间的数值,但是必须保证是 2的 n次幂。如果对象太大,一个 Region 放不下[超过Region大小的50%],那么就会直接放到 H(Humongous) 中。可通过参数 ‐XX:G1HeapRegionSize=32M 设置 Region大小。

  • G1 可用于新老年代
  • 新生代、老年代:标记整理

在 Oracle OpenJDK 官网中,有这样一段描述:G1 作为并发标记-清除收集器(CMS)的长期替代品。将 G1 与 CMS 进行比较,有一些差异使 G1 成为更好的解决方案

  • G1是一个压缩收集器。G1 进行了充分的压缩,避免了使用细粒度的自由列表进行分配,而是依赖于区域。这大大简化了收集器的某些部分,并基本上消除了潜在的碎片问题。
  • G1 提供了比 CMS 收集器更可预测的垃圾收集暂停,并允许用户指定所需的暂停目标。

在这里插入图片描述
运行步骤如下:

  • 初始标记:标记 GC Root 能够关联的对象,并且修改 TAMS 的值,需要暂停用户线程
  • 并发标记:从 GC Root 进行可达性分析,找出存活的对象,与用户线程并发执行。
  • 最终标记:修正在并发标记阶段因为用户程序的并发执行导致变动的数据,需暂停用户线程
  • 筛选回收:对各个 Region 的回收价值和成本进行排序,根据用户所期望的 GC 停顿时间制定回收计划。

6.5 ZGC(The Z Garbage Collector)

ZGC(The Z Garbage Collector)也是一种并发收集器,是 JDK 11 中推出的一款追求极致低延迟的实验性质的垃圾收集器。
在ZGC中,不管是物理上还是逻辑上,ZGC 中已经不存在新老年代的概念了,整体内存上会分为一个个 Page,当进行 GC 操作时会对 Page 进行压缩,因此没有碎片问题。

ZGC只能在64位的 Linux上使用,目前用得还比较少。

ZGC特定:
(1)可以达到 10ms 以内的停顿时间要求。
(2)支持 8MB~4TB 级别的堆内存,并声称未来可以支持 8MB ~ 16TB的堆内存。
(3)堆内存变大后停顿时间还是在10ms以内。

6.6 垃圾收集器分类

  1. 串行收集器:Serial,特点:适用内存较小的嵌入式设备。
  2. 并行收集器:Parallel,特点:高吞吐量,适用科学计算、后台处理等。
  3. 并发收集器:CMS、G1、ZGC,低延迟,适用 Web 交互场景。

6.7 垃圾收集器参数

  • -XX:+UseSerialGC:表示新生代和老年代都使用串行回收器。
  • -XX:+UseParNewGC:ParNew收集器是 Serial 收集器的多线程版本,表示新生代采用并行回收,老年代仍旧使用串行回收。
  • -XX:+UseParallelGC:表示新生代使用 Parallel 收集器,老年代使用串行收集器。
  • -XX:+UseParallelOldGC:表示新生代和老年代都使用并行收集器。
  • -XX:+UseConcMarkSweepGC:表示老年代采用 CMS 收集器。
  • -XX:+UseG1GC:表示新生代和老年代都采用G1收集器。

6.8 Reponsiveness and throughput

Reponsiveness:响应时间,也叫停顿时间,指垃圾收集器在进行垃圾回收时,终端应用执行响应的时间。

Throughput:吞吐量,指特定定时间内,应用程序执行工作量。

如何测量吞吐量??

  • 在给定时间内完成的事务数。
  • 批处理程序在一小时内可以完成的作业数。
  • 一小时内可以完成的数据库查询数。

6.9 垃圾收集发生时机

GC 是由 JVM 自动完成的,根据 JVM 系统环境而定,所以时机是不确定的。

当然,我们可以手动进行垃圾回收,比如调用 System.gc() 方法通知 JVM 进行一次垃圾回收,但是具体什么时刻运行也无法控制。 也就是说 System.gc() 只是通知要回收,什么时候回收由 JVM 决定。但是不建议手动调用该方法,因为 GC 消耗的资源比较大。

JVM在如下场景,会进行垃圾回收:
(1)当Eden区或者S区不够用了: Young GC 或 Minor GC
(2)老年代空间不够用了: Old GC 或 Major GC
(3)方法区空间不够用了: Metaspace GC

Full GC=Young GC+Old GC+Metaspace GC

七、JVM调优

7.1 参数调优

JVM常用参数列表:

设置JVM垃圾收集器

参数说明
-XX:+UseSerialGC表示新生代和老年代都使用串行回收器
-XX:+UseParNewGCParNew收集器是 Serial 收集器的多线程版本,表示新生代采用并行回收,老年代仍旧使用串行回收。
-XX:+UseParallelGC表示新生代使用 Parallel 收集器,老年代使用串行收集器。
-XX:+UseParallelOldGC表示新生代和老年代都使用并行收集器。
-XX:+UseConcMarkSweepGC表示老年代采用 CMS 收集器。
-XX:+UseG1GC表示新生代和老年代都采用G1收集器。

内存分配

参数含义说明
-XX:+InitialHeapSize=1024M初始化堆大小简写为-Xms100M
-XX:+MaxHeapSize=1024M最大堆大小简写为-Xmx100M
-XX:+NewSize=1024M设置年轻代大小
-XX:+MaxNewSize=1024M年轻代最大大小
-XX:+OldSize=1024M设置老年代大小
-XX:+MaxOldSize=1024M老年代最大大小
-XX:+MetaspaceSize=1024M设置方法区大小
-XX:+MaxMetaspaceSize=1024M方法区最大大小xxxx
-XX:+NewRatio=4新老年代所占堆空间比值比如 -XX:+NewRatio=4 ,表示新生代 : 老年代 = 1:4
-XX:+SurvivorRatio=8S0、S1和Eden区的比值比如 -XX:+SurvivorRatio=8,表示 Eden:S0:S1=8:1:1

其他参数

参数含义说明
-XX:+HeapDumpOnOutOfMemoryError启动堆内存溢出日志打印发生OOM,分析dump日志
-XX:+HeapDumpPath=heap.hprof指定堆内存溢出日志打印目录表示当前目录下生产一个 heap.hprof 日志文件
-XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+PrintGCDateStamps -Xloggc:g1-gc.log打印G1日志文件
-XX:+Xss128k设置每个线程的堆栈大小经验值是3000-5000最佳
-XX:+MaxTenuringThreshold=15Young区对象提升到Old区的最大临界值默认15
-XX:+InitiatingHeapOccupancyPercent=45触发并发GC周期,堆内存使用占比G1类的并发垃圾收集器,通过该参数触发GC,为0表示一直执行GC循环,默认45
-XX:+G1HeapWastePercentG1收集器允许浪费堆空间占比默认是10%,如果并发标记可回收的空间小于10%,则不会触发Mixed GC
-XX:+MaxGCPauseMillis=200msG1最大停顿时间停顿时间不能太小,太小会导致出现G1跟不上垃圾产生的速度。最终退化成Full GC。所以对这个参数的调优是一个持续的过程,逐步调整到最佳状态。
-XX:+ConcGCThreads=nCMS并发收集器使用的线程数

7.1 参数查看

(1)-XX:PrintFlagsFinal参数

用法:

java -XX:+PrintFlagsFinal -version 

结果:

[Global flags]
uintx AdaptivePermSizeWeight               = 20               {product}
uintx AdaptiveSizeDecrementScaleFactor     = 4                {product}
uintx AdaptiveSizeMajorGCDecayTimeScale    = 10               {product}
....

表格的每一行包括五列,来表示一个参数。

  • 第一列表示参数的数据类型
  • 第二列是名称
  • 第三列”=”表示第四列是参数的默认值,而”:=” 表明了参数被用户或者JVM赋值了。
  • 第四列为值
  • 第五列是参数的类别。

可以进行过滤,仅查看被修改项:

java -XX:+PrintFlagsFinal -version | grep ":"

使用 java -XX: +PrintFlagsFinal 输出到一个文件中

java -XX:+PrintFlagsFinal >params.txt

(2)通过 jps 命令查看
列出系统中所有的 Java 应用程序

用法:

jps
jps -l

(3)通过 jinfo 命令查看
jinfo 是 JDK 自带的命令,可以用来查看正在运行的 java 应用程序的扩展参数,包括Java System属性和JVM命令行参数;也可以动态的修改正在运行的 JVM 一些参数。当系统崩溃时,jinfo可以从core文件里面知道崩溃的Java应用程序的配置信息

用法:
在这里插入图片描述

no option 输出全部的参数和系统属性
-flag name 输出对应名称的参数
-flag [+|-]name 开启或者关闭对应名称的参数
-flag name=value 设定对应名称的参数
-flags 输出全部的参数
-sysprops 输出系统属性

(4)通过 stat 命令查看
Jstat是JDK自带的一个轻量级小工具。全称“Java Virtual Machine statistics monitoring tool”,它位于java的bin目录下,主要利用JVM内建的指令对Java应用程序的资源和性能进行实时的命令行的监控,包括了对Heap size和垃圾回收状况的监控。可见,Jstat是轻量级的、专门针对JVM的工具,非常适用。

用法:
在这里插入图片描述

-class:统计class loader行为信息 
-compile:统计编译行为信息 
-gc:统计jdk gc时heap信息 
-gccapacity:统计不同的generations(包括新生区,老年区,permanent区)相应的heap容量情况 
-gccause:统计gc的情况,(同-gcutil)和引起gc的事件 
-gcnew:统计gc时,新生代的情况 
-gcnewcapacity:统计gc时,新生代heap容量 
-gcold:统计gc时,老年区的情况 
-gcoldcapacity:统计gc时,老年区heap容量 
-gcpermcapacity:统计gc时,permanent区heap容量 
-gcutil:统计gc时,heap情况

# 查看某个java进程的类装载信息,每1000毫秒输出一次,共输出10次 
jstat ‐class PID 1000 10 

# 查看某个java进程的GC信息,每1000毫秒输出一次,共输出10次 
jstat ‐gc PID 1000 10

(5)通过 jstack 命令查看

  • jstack 命令用于打印指定 Java进程、核心文件或远程调试服务器的Java线程的 Java 堆栈跟踪信息。
  • jstack 命令可以生成 JVM 当前时刻的线程快照。线程快照是当前JVM内每一条线程正在执行的方法堆栈的集合,生成线程快照的主要目的是定位线程出现长时间停顿的原因,如线程间死锁、死循环、请求外部资源导致的长时间等待等。

用法:
在这里插入图片描述

(6)通过 jmap 命令查看

用法:

# 查看 Java内存信息(可以查看新生代、老年代、s0、s1、eden区信息)
jmap ‐heap PID 

# 显示Java堆中对象的统计信息,包括:对象数量、占用内存大小(单位:字节)和类的完全限定名。
# 如果指定了live参数,则只计算活动的对象
jmap -histo PID
jmap -histo:live PID

# 显示Java堆中元空间的类加载器的统计信息,包括:
#      - class_loader:当Java虚拟机运行时,类加载器对象的地址
#      - classes:已加载类的数量
#      - bytes:该类加载器加载的所有类的元数据所占的字节数
#      - parent_loader:父类加载器对象的地址,如果没有显示null。
#      - alive:是否存活的标识,表示类加载器对象是否将被垃圾回收。
#      - type:该类加载器的类名。
jmap -clstats PID

# 生成Java虚拟机的堆转储快照dump文件
jmap -dump:[live,]format=b,file=
# live参数是可选的,如果指定,则只转储堆中的活动对象;如果没有指定,则转储堆中的所有对象。
# format=b表示以hprof二进制格式转储Java堆的内存。
# file=<filename>用于指定快照dump文件的文件名。
# 如:jmap ‐dump:format=b,file=heap.hprof PID

八、常用工具

8.1 JDK常用工具

(1)jconsole
JConsole 是一个内置 Java 性能分析器

(2)jvisualvm
jvisualvm 也是 JDK 自带的一个 Java 性能分析器,功能非常强大,可以对堆内存进行 dump、快照以及性能可视化分析,也可以安装插件对堆外内存进行分析。

8.2 第三方通用工具 - Arthas

Arthas(阿尔萨斯) 是阿里巴巴开源的 Java 诊断工具,基本使用场景是定位复现一些生产环境比较难以定位问题。可以在线排查问题,以及动态追踪 Java代码,实时监控 JVM 状态等等。

8.3 内存分析工具

(1)MAT
MAT 是Memory Analyzer的简称,他是一宽功能强大的Java堆内存分析器。多用于查找内存泄露以及查看内存消耗情况。 基于Eclipse开发,是一款免费的Java性能分析功能。通过 MAT 可以直接打开 dump 日子文件,快速分析、定位问题。

下载安装【https://www.eclipse.org/mat/downloads.php】

(2)HeapHero
HeapHero是一款简单的,易用的内存分析工具,无需登录在线生成分析报告。官网地址:【https://heaphero.io/heap-index.jsp】

(3)Perfma
官网地址:【https://console.perfma.com/】

8.4 GC分析工具

1. GC日志

可以使用不同的参数设置不同的日志文件,比如:‐XX:+PrintGCDetails ‐XX:+PrintGCTimeStamps ‐XX:+PrintGCDateStamps ‐Xloggc:D:\gc.log

2. gcviewer
在 github 上搜索 gcviewer 项目,并下载到本地。
GCViewer 项目没有提供现成的 release 版本,利用如下 maven 编译命令即可完成 GCViewer 的编译工作,最终生成一个gcviewer-1.36.jar

# 编译
mvn clean install -DskipTests
# 运行
java ‐jar gcviewer‐1.36‐SNAPSHOT.jar 

3. gceasy
gceasy是一款可以分析gc日志,形成可视化的报表,支持快速排查问题,并且可以推荐jvm优化的配置(收费)
官网地址:【http://gceasy.io】

4. gcplot
gcplot 是一个灵活强大的jvm gc 查看,分析工具,方便的数据管理以及基于时间的数据筛选。
官网地址:【https://it.gcplot.com/】
推荐用docker 安装:

docker run ‐d ‐p 8088:80 gcplot/gcplot 

运行后访问 http://192.168.xx.xx:8080,默认账户 admin / admin

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/23424.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

2023年英语二大作文押题猜想(达立易考)

又到了考前大开脑洞的时间了&#xff01;每年一到这个时间点&#xff0c;关于押题猜题的话题就会铺天盖地而来&#xff0c;众多名师大咖更是会集毕生所学&#xff0c;期待可以在这个环节押中部分题目彰显实力&#xff0c;其中主观题就是大家集中关注的重要热点模块。押题听起来…

声纹识别开源工具 ASV-Subtools

今天非常荣幸有机会在Speechhome语音技术研讨会上分享我们团队在开源项目上的一些工作。今天我分享的主题是声纹识别开源工具ASV-Subtools。 今天我分享的主要有5个部分的内容&#xff0c;分别是背景介绍、工具介绍、实验结果、Subtools工程化、总结与展望。其中Subtools工程化…

【ROS】机械人开发五--ROS基本概念的程序实现

机械人开发五--ROS基本概念的程序实现一、开发工具二、RoboWare Studio的基本使用2.1 软件启动2.2 修改界面语言2.3 使用2.4 编译文件2.5 卸载三、话题通信四、话题的代码编写4.1 发布端4.2 接收端4.3 测试五、自定义消息5.1 自定义消息类型5.2 自定义消息发布端5.3 自定义消息…

el-menu动态加载路由,菜单的解决方案

先看需要实现的效果 这里有一级也有二级菜单&#xff0c;注意二级菜单的父目录&#xff08;”选项设置“点击不会跳转&#xff0c;只是展开目录&#xff09;&#xff0c;然后点击去详情页&#xff0c;需要跳到一个隐藏的路由&#xff0c;不在菜单展示的路由 还有一点要注意&…

LaTex常用技巧5:公式太长换行并加大括号

使用LaTex做笔记的时候发现公式太长&#xff0c;一行会超出页面&#xff0c;于是想到换行。 原来的代码&#xff0c;这里使用了包bm&#xff0c;测试的时候前面请使用\usepackage{bm}。 \begin{equation}_{i}^{G} {\bm{a}}\begin{cases} _{i}^{i-1}\ddot{\bm{p}}, &i1\\_…

web课程设计网页规划与设计 html+css+javascript+jquery+bootstarp响应式游戏网站Bootstrap模板(24页)

&#x1f389;精彩专栏推荐&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb; ✍️ 作者简介: 一个热爱把逻辑思维转变为代码的技术博主 &#x1f482; 作者主页: 【主页——&#x1f680;获取更多优质源码】 &#x1f393; web前端期末大作业…

网址,URL,域名,IP地址,DNS,域名解析(转载)

一、基本常识 互联网上的所有数据都是存储在主机(服务器)上互联网中的所有主机都拥有唯一的IP地址互联网中任意两台主机通信都是通过IP地址来实现 上网的实质 就是获取网址对应主机上的数据并在用户主机上进行展示(浏览器上) 疑问&#xff1a;互联网中的任意两台主机通信是依…

详细介绍百度ERNIE:通过知识集成增强表示

文章目录ERNIE简介相关工作采用矢量表示单词 &#xff0c;上下文无关的表示采用上下文来预测丢失的单词&#xff0c;没有考虑先验知识采用异构数据ERNIE的详细实现Transformer编码器知识整合基本级别掩码短语级别掩码实体级别掩码实验异构语料库预训练DLM&#xff08;对话语言模…

python自动化:桌面壁纸下载器,满足你对桌面壁纸的无限畅想!

随着计算机性能的提升&#xff0c;人们对计算机个性化的要求也越来越高了&#xff0c;自己使用的计算机当然要设置成自己喜欢的风格&#xff01; 对于桌面壁纸有着强烈要求的朋友们有福了&#xff0c;推荐一个微软免费畅玩无限高清壁纸的官网。 https://cn.bing.com/images/t…

深入学习数组

目录 一、一维数组 1、数组的创建和初始化 2、一维数组的使用 3、*一维数组在内存中的存储 二、二维数组 1、二维数组的创建和初始化 2、二维数组的使用 3、*二维数组在内存中的存储 三、数组越界 一、一维数组 1、数组的创建和初始化 数组是一组相同类型元素的集合。 数组…

UNIAPP实战项目笔记42 购物车页面新增收货地址

UNIAPP实战项目笔记42 购物车页面新增收货地址 设置新增收货地址页面布局和功能 具体内容图片自己替换哈&#xff0c;随便找了个图片的做示例 用到了vuex的状态机,具体位置见目录结构 代码 my-add-path.vue 页面部分 my-add-path.vue 设置页面布局 用到了vuex的状态机 <te…

steam搬砖副业,月入2万+,内含全套讲解

Steam平台是一款国外知名的数字游戏社交平台&#xff0c;steam游戏平台起初只是一个整合游戏的下载平台&#xff0c;随着软件的发展&#xff0c;逐渐演变为了游戏社交平台&#xff0c;steam是世界上目前最大的游戏平台之一&#xff0c;而「网易BUFF」是一款由网易公司推出&…

Unity3D简陋版跑酷游戏

目录 功能演示 功能简介 制作步骤 功能演示 链接&#xff1a;https://pan.baidu.com/s/1E_2JXWlVJNf3S5l-dH2UuQ提取码&#xff1a;dm5e 视频教学:Unity3D大作业 超级简陋版的跑酷游戏_哔哩哔哩_bilibili 功能简介 本次跑酷游戏主要从跑道&#xff0c;UI设计&#xff0c;…

[附源码]java毕业设计小区宠物管理系统

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

MyBatis--获取参数值

MyBatis获取参数值的两种方式 &#xff1a; ${} 和 #{} ${}的本质是字符串 &#xff0c;#{}的本质是占位符赋值 ${}使用字符串拼接的方式拼接sql &#xff0c;若为字符串类型或日期类型的字段进行赋值时&#xff0c;需要手动加单引号。 #{}使用占位符赋值的方式拼接sql &#x…

[附源码]java毕业设计小锅米线点餐管理系统

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

【Spring Cloud实战】Spring Cloud Bus消息总线

gitee地址&#xff1a;https://gitee.com/javaxiaobear/spring-cloud_study.git 在线阅读地址&#xff1a;https://javaxiaobear.gitee.io/ 1、概述 Spring Cloud Bus将分布式系统的节点与轻量级消息代理链接。这可以用于广播状态更改&#xff08;例如配置更改&#xff09;或其…

15.PyQt5中的事件系统之事件(QEvent)简介

PyQt5中的事件系统 一、什么是Qt中的事件 事件&#xff08;event&#xff09;是由窗口系统或者Qt自身产生的事情或动作的通称。当用户按下或者松开键盘或鼠标的按键时&#xff0c;就可以产生一个键盘或者鼠标事件&#xff1b;当某个窗口第一次显示的时候&#xff0c;就会产生一…

Pytorch的入门操作(二)

2、Pytorch 2.1 Pytorch的介绍和安装 目标&#xff1a; 知道如何安装Pytorch 2.1.1 Pytorch的介绍 Pytorch是Facebook发布的深度学习框架&#xff0c;由其易用性&#xff0c;友好性&#xff0c;深受广大用户青睐 2.1.2 Pytorch的版本 2.1.3 Pytorch的安装 安装地址介绍&…

Matlab论文插图绘制模板第65期—带等高线的曲面图(Surfc)

在之前的文章中&#xff0c;分享了Matlab曲面图的绘制模板&#xff1a; 这一次&#xff0c;再来分享一下带等高线的曲面图的绘制模板。 先来看一下成品效果&#xff1a; 特别提示&#xff1a;Matlab论文插图绘制模板系列&#xff0c;旨在降低大家使用Matlab进行科研绘图的门槛…