JVM-性能优化工具 MAT

一、MAT下载和安装

1、概述

MAT(Memory Analyzer Tool)工具是一款功能强大的]ava堆内存分析器。可以用于查找内存泄漏以及查看内存消耗情况。MAT是基于Eclipse开发的,不仅可以单独使用,还可以作为插件的形式嵌入在Eclipse中使用。是一款免费的性能分析工具,使用起来非常方便。

2、下载地址:

https://www.eclipse.org/mat/downloads.php

我目前电脑的JDK安装环境是1.8的,所以需要下载对应JDK1.8版本的MAT版本
在这里插入图片描述
在这里插入图片描述

3、安装

下载后解压,点击MemoryAnalyzer.exe进行启动
在这里插入图片描述

4、安装出现的报错问题

4.1、MAT版本和JDK版本不一致

问题描述:
要是直接下载最新版的MAT,可能需要高版本JDK才行。启动是需要JDK11或者更高的版本,我本地JDK版本是1.8,所以会报JDK版本不适合。
在这里插入图片描述
解决方法:
在MemoryAnalyzer.ini 中加入指定jdk的地址, (jdk不用安装直接下载 解压指定bin/javaw.exe就可)

-vm
D:/java/jdk1.8.0_211/binbin/javaw.exe
-vm
D:/java/jdk1.8.0_211/binbin/javaw.exe
-startup
plugins/org.eclipse.equinox.launcher_1.5.0.v20180512-1130.jar
--launcher.library
plugins/org.eclipse.equinox.launcher.win32.win32.x86_64_1.1.700.v20180518-1200
-vmargs
-Xmx1024m

4.2、堆dump文件较大、使用MAT打开的时候总是抛出 Java Heap Error

问题描述:
有时候线上产生的堆dump文件较大,如果你的hprof文件没有问题的话,使用MAT打开的时候总是抛出 Java Heap Error. 可能是默认的1024m内存不够用了。

解决办法:
找到MAT的安装目录,找到MemoryAnalyzer.ini 修改其中的-Xmx即可
在这里插入图片描述
将-Xmx1024m 调大即可
在这里插入图片描述

5、jmap命令拿到dump日志文件

jmap是Java虚拟机自带的一个命令行工具,可以用来生成JVM内存快照(Heap dump)文件。以下是使用jmap命令生成dump文件的步骤:

jmap -dump:format=b,file=heap.bin <pid>

通常情况下,在生产环境中使用jmap命令生成Heap dump文件时,建议把生成的文件下载到本地进行分析,以减少对生产环境的干扰。另外,在生成Heap dump文件时,一定要确保Java应用程序正常运行,否则可能会导致生成的文件不完整或者无法正确解析。

二、MAT工具排查分析OOM

1、故障现象:

集群应用服务器在高并发请求的情况下会不定时地因为响应超时而报警,但是很快又超时解除,恢复正常,如此反复,让运维人员非常苦恼。
原因分析: 来到一家新公司,一个重构项目的开发人员估计搞不动了,最后选择跑路,我的到来正好接盘了这个有好多bug的项目。配合测试功能测试完结束后,进行压测。发现查询接口只要并发一起来就会出现错乱的现象。先是排查原先写的代码是否有问题,没发现问题,然后我以为是脏读,调整的事务的隔离级别等等方法,发现还是解决不了。最后没办法在方法上加了一个synchronized锁,再进行压测时,虽然吞吐量不高,但是不会有报错的现象。等开始正式切换系统进行上线时。因为每天会有至少20w的查询量。只要某个时间段只要请求量很高就会出现连接超时的现象。当时也想到是因为加了synchronized造成高并发请求下,很多请求一直在等待,最后因为时间太久而造成的超时。所以我就下载了dump文件,使用MAT工具进行分析。果然是这个锁造成的。这是的我已经对代码稍微熟悉了,分析什么造成的错乱现象。发现代码有一处用到了共享变量,造成每次高并发去请求出现的错乱现象。我当时心里。。。
在这里插入图片描述
参考https://blog.csdn.net/cl939974883/article/details/124581664 文档,确实是synchronized造成的
在这里插入图片描述
下面详说一下MAT如何分析dump文件

2、MAT 分析 OOM 问题通常思路:

  1. 通过支配树功能或直方图功能查看消耗内存最大的类型,来分析内存泄露的大概原因;
  2. 查看那些消耗内存最大的类型、详细的对象明细列表,以及它们的引用链,来定位内存泄露的具体点;
  3. 配合查看对象属性的功能,可以脱离源码看到对象的各种属性的值和依赖关系,帮助我们理清程序逻辑和参数;
  4. 辅助使用查看线程栈来看 OOM 问题是否和过多线程有关,甚至可以在线程栈看到 OOM 最后一刻出现异常的线程。

3、使用MAT定位问题:

  • 定位问题方式一:

    现在有一个OOM后得到的堆转储文件 java_pid29569.hprof,现在要使用 MAT 的直方图支配树线程栈OQL 等功能来分析此次 OOM 的原因。

    首先,用 MAT 打开后先进入的是概览信息界面,可以看到整个堆是 437.6MB:
    在这里插入图片描述
    那么,这 437.6MB 都是什么对象呢?

    如图所示,工具栏的第二个按钮可以打开直方图,直方图按照类型进行分组,列出了每个类有多少个实例,以及占用的内存。可以看到,char[]字节数组占用内存最多,对象数量也很多,结合第二位的 java.lang.String 类型对象数量也很多,大概可以猜出(String 使用 char[]作为实际数据存储)程序可能是被字符串占满了内存,导致 OOM。
    在这里插入图片描述
    char[]上点击右键,选择 List objects->with incoming references,就可以列出所有的 char[]实例,以及每个 char[]的整个引用关系链:
    在这里插入图片描述
    随机展开一个 char[],如下图所示:
    在这里插入图片描述
    接下来,我们按照红色框中的引用链来查看,尝试找到这些大 char[]的来源:

  • 在①处看到,这些 char[]几乎都是 10000 个字符、占用 20000 字节左右(char 是 UTF-16,每一个字符占用 2 字节);

  • 在②处看到,char[]被 Stringvalue 字段引用,说明 char[]来自字符串;

  • 在③处看到,StringArrayListelementData 字段引用,说明这些字符串加入了一个 ArrayList 中;

  • 在④处看到,ArrayList 又被 FooServicedata 字段引用,这个 ArrayList 整个 RetainedHeap 列的值是 431MB。

  • 左侧的蓝色框可以查看每一个实例的内部属性,图中显示 FooService 有一个 data 属性,类型是 ArrayList

    Retained Heap(深堆):代表对象本身和对象关联的对象占用的内存;

    Shallow Heap(浅堆):代表对象本身占用的内存。
    比如,我们的 FooService 中的 data 这个 ArrayList 对象本身只有 16 字节,但是其所有关联的对象占用了 431MB 内存。这些就可以说明,肯定有哪里在不断向这个 List 中添加 String 数据,导致了 OOM。

    如果我们希望看到字符串完整内容的话,可以右键选择 Copy->Value,把值复制到剪贴板或保存到文件中:
    在这里插入图片描述
    这里,我们复制出的是 10000 个字符 a(下图红色部分可以看到)。
    看到这些,我们已经基本可以还原出真实的代码是怎样的了,定位到了问题代码。

  • 定位问题方式二:
    其实,我们之前使用直方图定位 FooService,已经走了些弯路。你可以点击工具栏中第三个按钮(下图左上角的红框所示)进入支配树界面。这个界面会按照对象的 Retained Heap 倒序直接列出占用内存最大的对象。
    在这里插入图片描述
    可以看到,第一位就是 FooService,整个路径是 FooSerice->ArrayList->Object[]->String->char[](蓝色框部分),一共有 21523 个字符串(绿色方框部分)。通常使用这种方式可以一步到位的定位出问题所在。

  • 借助MAT寻到具体问题原因
    我们就从内存角度定位到 FooService 是根源了。那么,OOM 的时候,FooService 是在执行什么逻辑呢?

    为解决这个问题,我们可以点击工具栏的第五个按钮(下图红色框所示)。打开线程视图,首先看到的就是一个名为 main 的线程(Name 列),展开后果然发现了 FooService
    在这里插入图片描述
    先执行的方法先入栈,所以线程栈最上面是线程当前执行的方法,逐一往下看能看到整个调用路径。

  • 因为我们希望了解 FooService.oom() 方法,看看是谁在调用它,它的内部又调用了谁,所以选择以 FooService.oom() 方法(蓝色框)为起点来分析这个调用栈。

  • 往下看整个绿色框部分,oom() 方法被 OOMApplicationrun 方法调用,而这个 run 方法又被 SpringAppliction.callRunner 方法调用。

  • 看到参数中的 CommandLineRunner 你应该能想到,OOMApplication 其实是实现了 CommandLineRunner 接口,所以是 SpringBoot 应用程序启动后执行的。

  • FooService 为起点往上看,从紫色框中的 CollectorsIntPipeline,大概也可以猜出,这些字符串是由 Stream 操作产生的。

  • 再往上看,可以发现在 StringBuilderappend 操作的时候,出现了 OutOfMemoryError 异常(黑色框部分),说明这这个线程抛出了 OOM 异常。

    我们看到,整个程序是 Spring Boot 应用程序,那么 FooService 是不是 SpringBean 呢,又是不是单例呢?

    如果能分析出这点的话,就更能确认是因为反复调用同一个 FooServiceoom 方法,然后导致其内部的 ArrayList 不断膨胀。

    点击工具栏的第四个按钮(如下图红框所示),来到 OQL 界面。在这个界面,我们可以使用类似 SQL 的语法,在 dump 中搜索数据(你可以直接在 MAT 帮助菜单搜索 OQL Syntax,来查看 OQL 的详细语法)。
    在这里插入图片描述
    比如,输入如下语句搜索 FooService 的实例:

    SELECT * FROM org.geekbang.time.commonmistakes.troubleshootingtools.oom.FooService
    

    在这里插入图片描述
    可以看到只有一个实例,然后我们通过 List objects 功能搜索引用 FooService 的对象:
    在这里插入图片描述
    可以看到,一共两处引用:

  • 第一处是,OOMApplication 使用了 FooService

  • 第二处是一个 ConcurrentHashMap。可以看到,这个 HashMapDefaultListableBeanFactorysingletonObjects 字段,可以证实 FooServiceSpring 容器管理的单例的 Bean

4、结论

到现在为止,虽然没看程序代码,但是已经大概知道程序出现 OOM 的原因和大概的调用栈了。再贴出程序来对比一下,果然和我们看到得一模一样:

@SpringBootApplication
public class OOMApplication implements CommandLineRunner {
    @Autowired
    FooService fooService;
    public static void main(String[] args) {
        SpringApplication.run(OOMApplication.class, args);
    }
    @Override
    public void run(String... args) throws Exception {
        //程序启动后,不断调用Fooservice.oom()方法
        while (true) {
            fooService.oom();
        }
    }
}
@Component
public class FooService {
    List<String> data = new ArrayList<>();
    public void oom() {
        //往同一个ArrayList中不断加入大小为10KB的字符串
        data.add(IntStream.rangeClosed(1, 10_000)
                .mapToObj(__ -> "a")
                .collect(Collectors.joining("")));
    }
}

到这里,我们使用 MAT 工具从对象清单、大对象、线程栈等视角,分析了一个 OOM 程序的堆转储。可以发现,有了堆转储,几乎相当于拿到了应用程序的源码 + 当时那一刻的快照,OOM 的问题无从遁形。

三、jvm-jps、jinfo、jstat、jstack、jmap 基本使用

给系统定位问题的时候,知识经验是基础,应用数据是依据,工具是手段,在jvm中,我们常见的数据包括: 运行日志、堆栈信息、GC信息、线程快照(threaddump/javacode)、堆快照(heapdump/hporf),jdk提供给我们了很实用的工具来分析,定位解决这些问题,这些工具包含于jdk中,并且以java实现,方便在不同的环境中不用安装其他依赖库即可使用,很是方便。下面分别介绍 jps、jinfo、jstat、jstack、jmap,本文使用的jdk版本为1.8.0_11

1、jps ( jvm process status tool ) 虚拟机进程工具

配置项作用
-q忽略主类的名称,只输出pid
-m输出启动类main函数的参数
-l输出主类名,如果进程执行的为jar,则输出jar路径
-v输出具体进程启动时jvm参数

1.命名格式

jps [options] pid

2.常用方式

  • jps -lv : 输出启动类名与启动时jvm参数,可以方便的看到各个tomcat的自定义参数配置
  • jps -lv |grep project_name : 在上述基础上过滤出自己想要查看的项目的信息

2、jinfo ( configuration info for java ) 显示虚拟机配置信息

1.常用用法

  • jinfo pid : 显示jvm系统属性与vm参数信息
  • jinfo -flags pid : 显示jvm vm参数信息,如最大最小堆,默认堆,垃圾收集器参数等
  • jinfo -sysprops pid : 显示jvm系统属性
  • jinfo -flag : 显示特定vm参数值,例如 jinfo -flag MaxHeapSize pid 输出pid的最大堆内存

3、jstat ( jvm statistics monitoring tool) 收集虚拟机各方面运行数据

1、语法格式

jstat [ option pid [interval[s|ms] [count]]]

说明: interval 表示循环时间间隔,默认单位为ms,可以在直接使用s/ms指定单位,如 60ms/1s, count 表示输出几次 例:

jstat gc pid 1s 20

每1s查询一次gc情况,查询20次

2、option 详解(主要分三类:类装载、垃圾收集、运行期编译状况)

配置项作用
-class监视类装载、卸载数量、总空间以及类装载所耗费的时间
-gc监视Java堆,包括Eden区、两survivor区、老年代、永久代等的容量、已用空间、GC时间合计等
-gccapacity与-gc基本相同,但关注点为Java堆各个区域使用到的最大、最小空间
-gcutil与-gc基本相同,但关注点为Java堆各个区域已使用空间占总空间的百分比
-gccause与-gcutil功能相同,但会额外输出导致上一次GC产生的原因
-gcnew监控新生代GC情况
-gcnewcapacity与-gcnew基本相同,但关注最大,最小空间
-gold监控老年代GC情况
-goldcapacity与-gcold基本相同,但关注最大,最小空间
-compiler输出被JIT编译过的方法、耗时等信息
-printcomplilation输出已经被JIT编译的方法

3、查看类装载卸载情况 jstat -class pid

属性释义
Loaded装载总数量
Bytes装载总大小
Unloaded卸载类的数量
Time加载和卸载类总共的耗时

4、查看GC情况 jstat -gc pid

属性释义
S0C新生代survivor0容量
S1C新生代survivor1容量
S0U新生代survivor0已使用大小
S1U新生代survivor1已使用大小
EC新生代eden区容量
EU新生代eden区已使用大小
OC老年代容量
OU老年代已使用大小
MC元数据容量,即方法区容量
MU元数据已使用空间
CCSC压缩类空间大小
CCSU压缩类空间使用大小
YGC新生代gc次数(young gc)
YGCT新生代gc时间(s)
FGC老生代gc次数(full gc)
GCT总的gc时间,包括young gc和full gc

5、查看GC情况,以百分比显示

jstat -gcutil pid

6、查看新生代GC情况

jstat -gcnew pid
属性释义
S0C新生代survivor0容量
S1C新生代survivor1容量
S0U新生代survivor0已使用大小
S1U新生代survivor1已使用大小
TT对象在新生代存活的次数
MTT对象在新生代存活的最大次数
DSS期望的幸存区大小
ECeden区大小
EUeden区已使用大小
YGCyoung gc次数
YGCTyoung gc 时间 (秒)

7、查看老年代GC情况

jstat -gcold pid

8、查看各空间容量

jstat -gccapacity pid
属性释义
NGCMN新生代最小容量
NGCMX新生代最大容量
NGC当前新生代容量
S0Csurvivor0大小
S1Csurvivor0大小
ECEDEN区大小
OGCMN老年代最小容量
OGCMX老年代最大容量
OGC当前老年代大小
MCMN元数据最小容量
MCMX元数据最大容量
CCSMN最小压缩类空间大小
CCSMX最大压缩类空间大小
CCSC当前压缩类空间大小)

9、查看编译情况

jstat -compiler pid

4、jmap ( memory map for java ) 虚拟机堆快照工具

1、常用用法

  • jmap -heap pid 查看当前jvm heapdump与垃圾收集器的使用情况
  • jmap -dump:format=b,file=/temp/filename.hprof pid 转储堆快照,生成hprof文件到指定路径
  • jmap -histo pid 列出当前heap中对象状况,附字节码与java对象映射表

5、jstack ( stack trace for java ) 虚拟机线程快照工具

效果演示: 会显示所有线程的各种信息,可以用来排查死锁,或线程长时间停滞的问题…

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

XML—DTD、 Schema

目录 DTD是什么&#xff1f; DTD有什么用途&#xff1f; DTD与XML有什么联系&#xff1f; DTD原理图 外部DTD DTD文件book.dtd: 使用外部DTD文件的XML文件 PCDATA XML 文档构建模块 一、元素 1、元素声明 ①、有元素&#xff1a; ②、空元素&#xff1a; ③、ANY…

Java系列 | MJDK 如何实现压缩速率的 5 倍提升?

MJDK 是基于 OpenJDK 构建的美团 JDK 发行版。本文主要介绍 MJDK 是如何在保障 java.util.zip.* API 及压缩格式兼容性的前提下&#xff0c;实现压缩/解压缩速率提升 5-10 倍的效果。希望相关的经验能够帮助到更多的技术同学。 1 前言 2 数据压缩技术 3 压缩技术在 Java 中的…

Langchain使用介绍之outparser 和memory

上一篇博客中对Langchain中prompt进行了详细的介绍&#xff0c;此篇博客将介绍Langchain中的outparser和memory。当调用大模型生成内容时&#xff0c;返回的内容默认是string类型&#xff0c;这对于我们获取response中的某些内容信息可能会带来障碍&#xff0c;例如返回的内容本…

STM32 CUBEMX CAN通信数据发送失败原因分析

CAN通信是一种数据通信协议&#xff0c;用于在不同设备之间进行通信。它是一种高效的、实时的、可靠的、多主机的、串行通信系统&#xff0c;通常用于汽车电子、工业自动化等领域。CAN通信协议是由德国BOSCH公司于1986年引入&#xff0c;并在欧洲和日本广泛使用。CAN通信具有独…

C# char曲线控件

一、char曲线显示随机数数据 using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Runtime.InteropServices; using System.Text; using System.Threading; using Syst…

任意文件读取

文章目录 渗透测试漏洞原理任意文件读取1. 任意文件读取概述1.1 漏洞成因1.2 漏洞危害1.3 漏洞分类1.4 任意文件读取1.4.1 文件读取1.4.2 任意文件读取1.4.3 权限问题 1.5 任意文件下载1.5.1 一般情况1.5.2 PHP实现1.5.3 任意文件下载 2. 任意文件读取攻防2.1 路径过滤2.1.1 过…

安达发|富士康科技集团利用自动排程APS软件打造智慧工厂

富士康科技集团作为全球领先的3C产品研发制造企业&#xff0c;近年来积极布局智能制造领域&#xff0c;通过引入先进的自动化排程系统(APS),成功打造了智慧工厂&#xff0c;提高了生产质量与效率&#xff0c;降低了生产成本。 富士康集团自2019年下半年提出在观澜厂区建立数字可…

W5100S-EVB-PICO进行UDP组播数据回环测试(九)

前言 上一章我们用我们的开发板作为UDP客户端连接服务器进行数据回环测试&#xff0c;那么本章我们进行UDP组播数据回环测试。 什么是UDP组播&#xff1f; 组播是主机间一对多的通讯模式&#xff0c; 组播是一种允许一个或多个组播源发送同一报文到多个接收者的技术。组播源将…

网络渗透day6-面试01

&#x1f609; 和渗透测试相关的面试问题。 介绍 如果您想自学网络渗透&#xff0c;有许多在线平台和资源可以帮助您获得相关的知识和技能。以下是一些受欢迎的自学网络渗透的平台和资源&#xff1a; Hack The Box: Hack The Box&#xff08;HTB&#xff09;是一个受欢迎的平…

华为数通方向HCIP-DataCom H12-821题库(单选题:161-180)

第161题 以下关于 URPF(Unicast Reverse Path Forwarding) 的描述, 正确的是哪一项 A、部署了严格模式的 URPF,也能够可以同时部署允许匹配缺省路由模式 B、如果部署松散模式的 URPF,默认情况下不需要匹配明细路由 C、如果部署松散模式的 URPF,如果需要检查默认路由,则…

ConsoleApplication17_2项目免杀(Fiber+VEH Hook Load)

加载方式FiberVEH Hook Load Fiber是纤程免杀&#xff0c;VEH是异常报错&#xff0c;hook使用detours来hook VirtualAlloc和sleep&#xff0c;通过异常报错调用实现主动hook 纤程Fiber的概念&#xff1a;纤程是比线程的更小的一个运行单位。可以把一个线程拆分成多个纤程&#…

骨传导耳机十大品牌怎么选,骨传导耳机十大品牌排行榜分享

作为一个拥有20多款骨传导耳机来说&#xff0c;我也算是资深的使用者了&#xff0c;在骨传导耳机刚开始兴起的时候&#xff0c;我就开始接触了&#xff0c;近几年越来越多的骨传导耳机品牌诞生&#xff0c;我也是入手了不少&#xff0c;所以也算是对骨传导耳机非常熟悉了&#…

网络有源号角(50W-100W)社区小区广播 工地语音播报,隧道广播,钢铁广播广播系统

网络有源号角&#xff08;50W-100W&#xff09;社区小区广播 工地语音播报&#xff0c;隧道广播&#xff0c;钢铁广播广播系统 SV-7042T 50W网络有源号角 SV-7042T是深圳锐科达电子有限公司的一款壁挂式网络有源号角&#xff0c;具有10/100M以太网接口&#xff0c;可将网络音…

【c++5道练习题】①

目录 一、有限制的累加 二、计算日期到天数转换 三、仅仅反转字母 四、 字符串的第一个唯一字符 五、字符串最后一个单词的长度 一、有限制的累加 题述&#xff1a; 求123...n&#xff0c;要求不能使用乘除法、for、while、if、else、switch、case等关键字以及条件判断语句…

计算机网络 | TCP 三次握手四次挥手 |半关闭连接

本来是不愿意写的&#xff0c;可是在实际场景&#xff0c;对具体的描述标志还是模糊不清&#xff0c;基础不扎实&#xff0c;就得承认&#xff01;&#xff01;&#xff01; TCP 连接建立需要解决三大问题&#xff1a; 知道双方存在约定一些参数&#xff0c;如最大滑动窗口值、…

Stable Diffusion 提示词技巧

文章目录 背景介绍如何写好提示词提示词的语法正向提示词负向提示词 随着AI技术的不断发展&#xff0c;越来越多的新算法涌现出来&#xff0c;例如Stable Diffusion、Midjourney、Dall-E等。相较于传统算法如GAN和VAE&#xff0c;这些新算法在生成高分辨率、高质量的图片方面表…

YOLOv5模型压缩:综述

YOLOv5模型压缩:综述 AbstractIntroduction剪枝基于ln-范数修剪模型Feature map activationBatch normalization scaling factor (BNSF)First-order derivativeMutual informationGranularity of Pruning非结构化剪枝结构化剪枝基于通道的修剪基于滤波器的修剪基于核的剪枝关于…

次高端白酒:一场冰火两重的「战局」

【潮汐商业评论/ 原创】 夜深人静&#xff0c;Andy突然想起还没有给爷爷准备生日礼物。 “送酒肯定能让他老人家开心&#xff0c;但是买什么品牌呢&#xff1f;茅台太贵&#xff0c;其他好酒还真不熟。”&#xff0c;对于白酒研究不多的Andy来说&#xff0c;如何挑选到一款称…

【锁】定时任务推送数据-redission加锁实例优化

文章目录 redission 加锁代码-有问题优化代码看门狗是什么&#xff1f; redission 加锁代码-有问题 /*** 收货入库物料标签(包装码)推送接口** throws Exception*/public void synReceiveMaterialTags() throws Exception {String tag DateFormatUtils.format(new Date(), &qu…

自动化实时在线静电监控系统的构成

自动化实时在线静电监控系统是一种帮助企业监测和管理静电问题的技术解决方案。静电在许多工业和商业环境中都是一个潜在的风险和生产问题。通过使用这样的监控系统&#xff0c;企业可以及时发现并采取对策来预防或减轻可能的静电问题。 该系统通常由以下组成部分构成&#xf…