JVM 调优

news/2024/5/6 1:43:10/文章来源:https://blog.csdn.net/echizao1839/article/details/130367569

        

      大部分的情况都是由于企业内部代码逻辑不合理导致。

JVM内部性能优化

  • 栈上分配
  • 方法内联
  • JVM的自适应调整

JVM改错

  • 大并发内存不足
  • OOM 内存泄漏
  • GC频繁
  • CPU飙升

JVM的调优的原则是让你各项指标尽可能的利用到你硬件的性能瓶颈。

JVM的性能优化可以分为代码层面和非代码层面。

在代码层面,大家可以结合字节码指令进行优化,比如一个循环语句,可以将循环不相关的代码提 取到循环体之外,这样在字节码层面就不需要重复执行这些代码了。

在非代码层面,一般情况可以从内存、  gc以及cpu占用率等方面进行优化。

注意,JVM调优是一个漫长和复杂的过程,而在很多情况下,JVM是不需要优化的,因为JVM本身已经做了很多的内部优化操作。

一,JVM参数

1,标准参数

-version 
-help 
-server 
-cp

2,非标准参数[ -X ]

也就是在JDK各个版本中可能会变动
-Xint 解释执行 
-Xcomp 第一次使用就编译成本地代码 
-Xmixed 混合模式,JVM自己来决定

3,非标准化参数 [ -XX ]

相对不稳定,主要用于JVM调优和Debug
a.Boolean类型 
格式:-XX:[+-]<name> +或-表示启用或者禁用name属性 
比如:-XX:+UseConcMarkSweepGC 表示启用CMS类型的垃圾回收器 -XX:+UseG1GC 表示启用G1类型的垃圾回收器 
b.非Boolean类型 
格式:-XX<name>=<value>表示name属性的值是value 
比如:-XX:MaxGCPauseMillis=500

4,其他参数

-Xms1000M等价于-XX:InitialHeapSize=1000M 
-Xmx1000M等价于-XX:MaxHeapSize=1000M 
-Xss100等价于-XX:ThreadStackSize=100

所以这块也相当于是-XX类型的参数

5,查看参数

java -XX:+PrintFlagsFinal -version > flags.txt

值得注意的是"="表示默认值,":="表示被用户或JVM修改后的值

要想查看某个进程具体参数的值,可以使用jinfo
一般要设置参数,可以先查看一下当前参数是什么,然后进行修改

6,设置参数的常见方式

  • 开发工具中设置比如IDEA,eclipse
  • 运行jar包的时候:java -XX:+UseG1GC xxx.jar
  • web容器比如tomcat,可以在脚本中的进行设置
  • 通过jinfo实时调整某个java进程的参数(参数只有被标记为manageable的flags可以被实时修改)

7,实践和单位换算

(1)设置堆内存大小和参数打印 -Xmx100M -Xms100M -XX:+PrintFlagsFinal 
(2)查询+PrintFlagsFinal的值 :=true 
(3)查询堆内存大小MaxHeapSize := 104857600 
(4)换算 104857600(Byte)/1024=102400(KB) 102400(KB)/1024=100(MB) 
(5)结论 104857600是字节单位
1Byte(字节)=8bit(位)
1KB=1024Byte(字节)
1MB=1024KB
1GB=1024MB
1TB=1024GB

8,常用参数含义

-XX:CICompilerCount=3
最大并行编译数
如果设置大于1,虽然编译速度 会提高,但是同样影响系统稳定 性,会增加JVM崩溃的可能 -XX:InitialHeapSize=100M 
初始化堆大小
简写-Xms100M -XX:MaxHeapSize=100M 
最大堆大小 
简写-Xms100M -XX:NewSize=20M 
设置年轻代的大小 -XX:MaxNewSize=50M 
年轻代最大大小 -XX:OldSize=50M 
设置老年代大小 -XX:MetaspaceSize=50M 
设置方法区大小-XX:MaxMetaspaceSize=50M
方法区最大大小 -XX:+UseParallelGC
使用UseParallelGC 
新生代,吞吐量优先-XX:+UseParallelOldGC 
使用UseParallelOldGC 
老年代,吞吐量优先 -XX:+UseConcMarkSweepGC 
使用CMS 
老年代,停顿时间优先 -XX:+UseG1GC 
使用G1GC 
新生代,老年代,停顿时间优先-XX:NewRatio 
新老生代的比值
比如-XX:Ratio=4,则表示新生代: 老年代=1:4,也就是新生代占整 个堆内存的1/5 -XX:SurvivorRatio 
两个S区和Eden区的比值 
比如-XX:SurvivorRatio=8,也就 是(S0+S1):Eden=2:8,也就是一 个S占整个新生代的1/10 -XX:+HeapDumpOnOutOfMemoryError 
启动堆内存溢出打印 
当JVM堆内存发生溢出时,也就 是OOM,自动生成dump文件 -XX:HeapDumpPath=heap.hprof 
指定堆内存溢出打印目录 
表示在当前目录生成一个 heap.hprof文件 -XX:+PrintGCDetails 
-XX:+PrintGCTimeStamps 
-XX:+PrintGCDateStamps 
-Xloggc:g1- gc.log 
打印出GC日志 
可以使用不同的垃圾收集器,对 比查看GC情况 -Xss128k 
设置每个线程的堆栈大小
经验值是3000-5000最佳 -XX:MaxTenuringThreshold=6 
提升年老代的最大临界值 
默认值为 15 -XX:InitiatingHeapOccupancyPercent 
启动并发GC周期时堆内存使用占比 
G1之类的垃圾收集器用它来触发 并发GC周期,基于整个堆的使用 率,而不只是某一代内存的使用比. 值为 0 则表示”一直执行GC循环”. 默认值为 45. -XX:G1HeapWastePercent 
允许的浪费堆空间的占比
默认是10%,如果并发标记可回 收的空间小于10%,则不会触发 MixedGC。 -XX:MaxGCPauseMillis=200ms 
G1最大停顿时间 
暂停时间不能太小,太小的话就 会导致出现G1跟不上垃圾产生的 速度。最终退化成Full GC。所以 对这个参数的调优是一个持续的 过程,逐步调整到最佳状态。 -XX:ConcGCThreads=n 
并发垃圾收集器使用的线程数量 
默认值随JVM运行的平台不同而 不同 -XX:G1MixedGCLiveThresholdPercent=65 
混合垃圾回收周期中要包括的旧区 
域设置占用率阈值 
默认占用率为 65%-XX:G1MixedGCCountTarget=8 
设置标记周期完成后,对存活数据 上限为 G1MixedGCLIveThresholdPercent 的旧区域执行混合垃圾回收的目标次数
默认8次混合垃圾回收,混合回 收的目标是要控制在此目标次数以内 -XX:G1OldCSetRegionThresholdPercent=1 
描述Mixed GC时,Old Region被加 入到CSet中
默认情况下,G1只把10%的Old Region加入到CSet中

二,常用命令

1,jps

查看java进程
The jps command lists the instrumented Java HotSpot VMs on the target system. The
command is limited to reporting information on JVMs for which it has the access
permissions.

 2,jinfo

(1)实时查看和调整JVM配置参数

The jinfo command prints Java configuration information for a specified Java
process or core file or a remote debug server. The configuration information
includes Java system properties and Java Virtual Machine (JVM) command-line
flags.
(2)查看用法

jinfo -flag name PID 查看某个java进程的name属性的值

jinfo -flag MaxHeapSize PID 
jinfo -flag UseG1GC PID

(3)修改 

参数只有被标记为manageable的flags可以被实时修改

jinfo -flag [+|-] PID jinfo -flag <name>=<value> PID

(4)查看曾经赋过值的一些参数

jinfo -flags PID

 3,jstat

(1)查看虚拟机性能统计信息

The jstack command prints Java stack traces of Java threads for a specified Java process, core file, or remote debug server.

(2) 查看类装载信息

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

(3)查看垃圾收集信息 

jstat -gc PID 1000 10

4jstack 

  (1)查看线程堆栈信息

The jstack command prints Java stack traces of Java threads for a specified Java process, core file, or remote debug server.

(2)用法

jstack PID

 (3)排查死锁案例

//运行主类
public class DeadLockDemo {public static void main(String[] args) {DeadLock d1 = new DeadLock(true);DeadLock d2 = new DeadLock(false);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锁 ");}}}} else {while (true) {synchronized(MyLock.obj2) {System.out.println(Thread.currentThread().getName() + "----否则获得obj2锁 ");synchronized(MyLock.obj1) {System.out.println(Thread.currentThread().getName() + "--- - 否则获得obj1锁 ");}}}}}

jstack分析

把打印信息拉到最后可以发现 

5,jmap

  (1)生成堆转储快照

The jmap command prints shared object memory maps or heap memory details of a specified process, core file, or remote debug server.

(2)打印出堆内存相关信息

jmap -heap PIDjinfo -flag UsePSAdaptiveSurvivorSizePolicy 35352
-XX:SurvivorRatio=8

 (3)  dump出堆内存相关信息

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

 (4)要是在发生堆内存溢出的时候,自动dump出该文件

一般在开发中,  JVM参数可以加上下面两句,这样内存溢出时,会自动dump出该文件

​​​​​​​-XX:+HeapDumpOnOutOfMemoryError 
-XX:HeapDumpPath=heap.hprof

三,内存

正常情况下不需要设置,那如果是促销或者秒杀的场景呢?

每台机器配置2c4G,以每秒3000笔订单为例,整个过程持续60秒

1,内存溢出(OOM)

一般会有两个原因:

(1)大并发情况下

(2)内存泄露导致内存溢出

2,大并发[秒杀]

浏览器缓存、本地缓存、验证码

CDN静态资源服务器

集群+负载均衡

动静态资源分离、限流[基于令牌桶、漏桶算法]

应用级别缓存、接口防刷限流、队列、  Tomcat性能优化

异步消息中间件

Redis热点数据对象缓存

分布式锁、数据库锁

5分钟之内没有支付,取消订单、恢复库存等

3,内存泄露导致内存溢出

ThreadLocal引起的内存泄露,最终导致内存溢出

public class TLController {@RequestMapping(value = "/tl")public String tl(HttpServletRequest request) {ThreadLocal < Byte[] > tl = new ThreadLocal < Byte[] > ();// 1MBtl.set(new Byte[1024 * 1024]);return "ok";}
}

(1)  top命令查看

top
top -Hp PID

(2)  jstack查看线程情况,发现没有死锁或者IO阻塞的情况

jstack PID
java -jar arthas.jar   --->   thread

(3)查看堆内存的使用,发现堆内存的使用率已经高达88.95%

jmap -heap PID
java -jar arthas.jar   --->   dashboard

(4)此时可以大体判断出来,发生了内存泄露从而导致的内存溢出,那怎么排查呢?​​​​​​​

jmap -histo:live PID | more获取到jvm.hprof文件,上传到指定的工具分析,比如heaphero.io
获取使用Memory Analyzer Tool 进行分析

四,垃圾收集器的选择

吞吐量和停顿时间

  • 停顿时间
垃圾收集器进行垃圾回收终端应用执行响应的时间
  • 吞吐量
运行用户代码时间/(运行用户代码时间+垃圾收集时间)
这两个指标也是评价垃圾回收器好处的标准。
如何选择合适的垃圾收集器
https://docs.oracle.com/javase/8/docs/technotes/guides/vm/gctuning/collectors.html#
sthref28
  • 优先调整堆的大小让服务器自己来选择
  • 如果内存小于100M,使用串行收集器
  • 如果是单核,并且没有停顿时间要求,使用串行或JVM自己选
  • 如果允许停顿时间超过1秒,选择并行或JVM自己选
  • 如果响应时间最重要,并且不能超过1秒,使用并发收集器

对于G1收集

JDK 7开始使用,JDK 8非常成熟,JDK 9默认的垃圾收集器,适用于新老生代。
是否使用G1收集器?
(1)50%以上的堆被存活对象占用
(2)对象分配和晋升的速度变化非常大
(3)垃圾回收时间比较长
G1中的RSet

全称Remembered Set,记录维护Region中对象的引用关系

试想,在G1垃圾收集器进行新生代的垃圾收集时,也就是Minor GC,假如该对象被老年代的Region中所引用,这时候新生代的该对象就不能被回收,怎么记录呢?
不妨这样,用一个类似于hash的结构,key记录region的地址,value表示引用该对象的集合,这样就能知道该对象被哪些老年代的对象所引用,从而不能回收
如何开启需要的垃圾收集器
(1)串行 -XX:+UseSerialGC -XX:+UseSerialOldGC 
(2)并行(吞吐量优先): -XX:+UseParallelGC -XX:+UseParallelOldGC 
(3)并发收集器(响应时间优先) -XX:+UseConcMarkSweepGC -XX:+UseG1GC

五,G1优化

是否选用G1

官网  https://docs.oracle.com/javase/8/docs/technotes/guides/vm/G1.html#use_cases

(1) 50%以上的堆被存活对象占用

(2) 对象分配和晋升的速度变化非常大

(3) 垃圾回收时间比较长

    (1)使用G1GC垃圾收集器: -XX:+UseG1GC

修改配置参数,获取到gc日志,使用GCViewer分析吞吐量和响应时间

Throughput

99.16%

Min Pause

0.00016s

Max Pause 0.0137s

Avg Pause

0.00559s

GC count

12

   (2)调整内存大小再获取gc日志分析

比如设置堆内存的大小,获取到gc日志,使用GCViewer分析吞吐量和响应时间

Throughput

98.89%

Min Pause

0.00021s

Max Pause 0.01531s

Avg Pause

0.00538s

GC count

12

(3)调整最大停顿时间

比如设置最大停顿时间,获取到gc日志,使用GCViewer分析吞吐量和响应时间

Throughput

98.96%

Min Pause

0.00015s

Max Pause 0.01737s

Avg Pause

0.00574s

GC count

12

(4)启动并发GC时堆内存占用百分比

-XX:InitiatingHeapOccupancyPercent=45G1用它来触发并发GC周期 ,基于整个堆的使用率 ,而不只是某一代内存的使用比例。值为 0 则表示“一直执行 GC循环)'. 默认值为 45 (例如 , 全部的 45% 或者使用了45%).

比如置该百分比参数,获取到gc日志,使用GCViewer分析吞吐量和响应时间

Throughput

98.11%

Min Pause

0.00406s

Max Pause 0.00532s

Avg Pause

0.00469s

GC count

12

G1调优最佳实战

官网

https://docs.oracle.com/javase/8/docs/technotes/guides/vm/gctuning/g1_gc_tuning.html#r​​​​​​​ecommendations

(1)不要手动设置新生代和老年代的大小,只要设置整个堆的大

why:  https://blogs.oracle.com/poonam/increased-heap-usage-with-g1-gc

G1收集器在运行过程中,会自己调整新生代和老年代的大小

其实是通过adapt代的大小来调整对象晋升的速度和年龄,从而达到为收集器设置的暂停时间目标 如果手动设置了大小就意味着放弃了G1的自动调优

(2)不断调优暂停时间目标

一般情况下这个值设置到100ms或者200ms都是可以的(不同情况下会不一样),但如果设置成50ms就不 太合理。暂停时间设置的太短,就会导致出现G1跟不上垃圾产生的速度。最终退化成Full GC。所以对 这个参数的调优是一个持续的过程,逐步调整到最佳状态。暂停时间只是一个目标,并不能总是得到满 足。

(3)使用-XX:ConcGCThreads=n来增加标记线程的数量

IHOP如果阀值设置过高,可能会遇到转移失败的风险,比如对象进行转移时空间不足。如果阀值设置过 低,就会使标记周期运行过于频繁,并且有可能混合收集期回收不到空间。

IHOP值如果设置合理,但是在并发周期时间过长时,可以尝试增加并发线程数,调高 ConcGCThreads。

(4)  MixedGC调优

-XX:InitiatingHeapOccupancyPercent-XX:G1MixedGCLiveThresholdPercent-XX:G1MixedGCCountTarger-XX:G1OldCSetRegionThresholdPercent

 (5)适当增加堆内存大小

(6)不正常的Full GC 

有时候发现系统刚刚启动的时候,就会发生一次Full GC,但是老年代空间比较充足,一般是由Metaspace 域引起的。可以通过MetaspaceSize适当增加其大家,比如256M

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

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

相关文章

PyTorch实战3:天气识别

&#x1f368; 本文为&#x1f517;365天深度学习训练营 中的学习记录博客&#x1f366; 参考文章&#xff1a;365天深度学习训练营-第P3周&#xff1a;天气识别&#x1f356; 原作者&#xff1a;K同学啊|接辅导、项目定制 目录 一、前期准备1、导入数据2、transforms.Compose详…

【Python入门第五十四天】Python丨NumPy ufuncs

什么是 ufuncs&#xff1f; ufuncs 指的是“通用函数”&#xff08;Universal Functions&#xff09;&#xff0c;它们是对 ndarray 对象进行操作的 NumPy 函数。 为什么要使用 ufuncs&#xff1f; ufunc 用于在 NumPy 中实现矢量化&#xff0c;这比迭代元素要快得多。 它们…

线程的生命周期以及sleep()方法和wait()方法

三种休眠状态&#xff1a;Blocked&#xff0c;Waiting&#xff0c;Timed_Waiting 注意两个Blocked态是不一样的&#xff0c;上面的Blocked只要睡眠时间到了马上进入运行态&#xff0c;下面处于Blocked的线程还需要抢到锁才能进入运行态 sleep()和wait()方法&#xff1a; sleep…

【hello Linux】进程间通信——匿名管道

目录 前言&#xff1a; 总结下上述的内容&#xff1a; 1. 进程间通信目的 2. 进程间通信的分类 1. 匿名管道 2. 匿名管道的使用 1. 匿名管道的创建 2. 使用匿名管道进行父子间通信 Linux&#x1f337; 前言&#xff1a; 进程具有独立性&#xff0c;拥有独立的数据、代码及其他…

论文阅读:PVO: Panoptic Visual Odometry

全景视觉里程计、同时做全景分割和视觉里程计 连接&#xff1a;PVO: Panoptic Visual Odometry 0.Abstract 我们提出了一种新的全景视觉里程计框架PVO&#xff0c;以实现对场景运动、几何和全景分割信息的更全面的建模。我们将视觉里程计(VO)和视频全景分割(VPS)在一个统一的…

STM32F4_SRAM中调试代码

目录 1. 在RAM中调试代码 2. STM32的三种存储方式 3. STM32的启动方式 4. 实验过程 通过上一节的学习&#xff0c;我们已经了解了SRAM静态存储器&#xff1b; 1. 在RAM中调试代码 一般情况下&#xff0c;我们在MDK中编写工程应用后&#xff0c;调试时都是把程序下载到芯片…

Java_异常

Java_异常 1.什么是异常 ​ 生活中的异常&#xff1a;感冒发烧、电脑蓝屏、手机死机等。 ​ 程序中的异常&#xff1a;磁盘空间不足、网络连接中断、被加载的资源不存在等。 ​ 程序异常解决办法&#xff1a;针对程序中非正常情况&#xff0c;Java语言引入了异常&#xff0…

注意力机制:基于Yolov5/Yolov7的Triplet注意力模块,即插即用,效果优于cbam、se,涨点明显

论文&#xff1a;https://arxiv.org/pdf/2010.03045.pdf 本文提出了可以有效解决跨维度交互的triplet attention。相较于以往的注意力方法&#xff0c;主要有两个优点&#xff1a; 1.可以忽略的计算开销 2.强调了多维交互而不降低维度的重要性&#xff0c;因此消除了通道和权…

日撸 Java 三百行day38

文章目录 说明day381.Dijkstra 算法思路分析2.Prim 算法思路分析3.对比4.代码 说明 闵老师的文章链接&#xff1a; 日撸 Java 三百行&#xff08;总述&#xff09;_minfanphd的博客-CSDN博客 自己也把手敲的代码放在了github上维护&#xff1a;https://github.com/fulisha-ok/…

VR全景图片,探究VR全景图片为何如此受欢迎?

随着科技的不断进步&#xff0c;虚拟现实技术逐渐渗透到我们的日常生活中&#xff0c;为我们带来了许多前所未有的体验和乐趣。而其中&#xff0c;VR全景图片作为一种基于虚拟现实技术的图片展示形式&#xff0c;不仅在旅游、房地产、教育等领域得到了广泛的应用&#xff0c;也…

c++强制类型转换:

强制类型转换&#xff1a;1. const属性用const_cast。 案例&#xff1a; 说明&#xff1a;该变量可以将变量的const 的属性去掉。如该案例&#xff0c;转换后修改x的值是合法的。2. 基本类型转换用static_cast。 案例&#xff1a; 说明&#xff1a;一般用在(1)基本类型&#xf…

学系统集成项目管理工程师(中项)系列10_立项管理

1. 系统集成项目管理至关重要的一个环节 2. 重点在于是否要启动一个项目&#xff0c;并为其提供相应的预算支持 3. 项目建议 3.1. Request for Proposal, RFP 3.2. 立项申请 3.3. 项目建设单位向上级主管部门提交的项目申请文件&#xff0c;是对拟建项目提出的总体设想 3…

基于centos7:Harbor-2.7.2部署和安装教程

基于centos7&#xff1a;Harbor-2.7.2部署和安装教程 1、软件资源介绍 Harbor是VMware公司开源的企业级DockerRegistry项目&#xff0c;项目地址为https://github.com/vmware/harbor。其目标是帮助用户迅速搭建一个企业级的Dockerregistry服务。它以Docker公司开源的registry…

WPF学习

一、了解WPF的框架结构 &#xff08;第一小节随便看下就可以&#xff0c;简单练习就行&#xff09; 1、新建WPF项目 xmlns&#xff1a;XML的命名空间 Margin外边距&#xff1a;左上右下 HorizontalAlignment&#xff1a;水平位置 VerticalAlignment&#xff1a;垂直位置 2…

Timer0/1设置时钟计算中断时间

时钟一般分为外部晶振时钟和内部时钟&#xff0c;相对而说&#xff0c;外部晶振时钟的精准度比内部系统时钟高&#xff0c;时间计算的更准。除非产品需要一般都不会用外部晶振时钟&#xff0c;因为好的东西贵啊&#xff0c;成本高。 本文主要介绍如何利用时钟设置Timer0/1&…

厨电新十年,不可逆的行业分化与老板电器的数字进化

“人生就像滚雪球&#xff0c;最重要之事是发现湿雪和长长的山坡。”股神巴菲特的这句名言&#xff0c;让坡是否长、雪是否厚成为人们评价一个行业、一家公司的标准之一。 家电行业&#xff0c;厨电曾是最后一块“坡长雪厚”之地&#xff0c;投资者也对相关企业给出了相当的热…

MySQL根据中文姓名排序查询

在MySQL中当说到进行排序查询时&#xff0c;大家的第一反应就是使用 ORDER BY 方法指定列进行排序&#xff0c;但是如果要指定列为中文数据按照首字母排序时&#xff0c;就会发现 ORDER BY 方法排序的顺序其实是有问题的。 我们先来测试下正常使用 ORDER BY 排序&#xff1a; 指…

35岁程序员被裁赔偿27万,公司又涨薪让我回去,前提是退还补偿金,能回吗?

在大多数人眼里&#xff0c;35岁似乎都是一道槛&#xff0c;互联网界一直都有着“程序员是吃青春饭”的说法&#xff0c;。 如果在35岁的时候被裁能获得27万的赔偿&#xff0c;公司又涨薪请你回去上班&#xff0c;你会怎么选&#xff1f; 最近&#xff0c;就有一位朋友在网上…

剑指 Offer 42. 连续子数组的最大和:C语言解法

剑指 Offer 42. 连续子数组的最大和 - 力扣&#xff08;Leetcode&#xff09; 输入一个整型数组&#xff0c;数组中的一个或连续多个整数组成一个子数组。求所有子数组的和的最大值。 要求时间复杂度为O(n)。 实例&#xff1a; 输入: nums [-2,1,-3,4,-1,2,1,-5,4] 输出: …

SOLIDWORKS认证考试流程

一、SOLIDWORKS认证考试前的准备工作 1、检查电脑硬件设备是否可以正常使用&#xff0c;如键盘鼠标等。 2、检查Solidworks软件是否可以正常使用。 3、关闭电脑所有杀毒软件。 4、检查电脑网络&#xff08;外网&#xff09;是否正常。 5.请联系我们获取考试系统软件安装包。…