jvm调优主要是调哪里(JVM 性能调优方法)
本文目录
JVM 性能调优方法
JVM性能调优有很多设置,这个参考JVM参数即可.
主要调优的目的:
控制GC的行为.GC是一个后台处理,但是它也是会消耗系统性能的,因此经常会根据系统运行的程序的特性来更改GC行为
控制JVM堆栈大小.一般来说,JVM在内存分配上不需要你修改,(举例)但是当你的程序新生代对象在某个时间段产生的比较多的时候,就需要控制新生代的堆大小.同时,还要需要控制总的JVM大小避免内存溢出
控制JVM线程的内存分配.如果是多线程程序,产生线程和线程运行所消耗的内存也是可以控制的,需要通过一定时间的观测后,配置最优结果。
jvm性能调优都做些什么
主要都是调整JVM占用的内存空间
项目启动时jvm占用初始内存大小,最大占用多少
eden 调整
新生代gc次数,进入老年代
等,还有很多。针对不同情况cpu密集 or io密集,对jvm的调整
JVM调优常用参数配置
说明:
1、一般初始堆和最大堆设置一样,因为:现在内存不是什么稀缺的资源,但是如果不一样,从初始堆到最大堆的过程会有一定的性能开销,所以一般设置为初始堆和最大堆一样。64位系统理论上可以设置为无限大,但是一般设置为 4G ,因为如果再大,JVM进行垃圾回收出现的暂停时间会比较长,这样全GC过长,影响JVM对外提供服务,所以不能太大。一般设置为4G。
2、-XX:NewRaio和-XX:SurvivorRatio这两个参数,都是设置年轻代和年老代的大小的,设置一个即可,第一是设置年轻代的大小,第二个是设置比值,理论上设置一个既可以满足需求
打印GC回收的过程日志信息
以下配置主要针对分代收集回收算法而言
年轻代的设置很关键
JVM中最大堆大小有三方面限制:相关操作系统的数据模型(32bit还是64bit)限制:系统的可用虚拟内存限制;系统的可用物理内存限制。32位系统下,一般限制在1.5G-2G;64位操作系统对内存没有限制。在Windows Server 2003系统,****物理内存,*****下测试,最大设置为1478m。
典型设置:
JVM给了三种选择:串行收集器,并行收集器,并发收集器,但是串行收集器只适用于小数据量的情况,一般不考虑使用了,所以这里只针对并行收集器和并发收集器。默认情况下,*****以前是使用的串行收集器,如果想使用其他收集器需要在启动时加入相应的参数, *****以后,JVM会根据系统当前的配置进行判断
吞吐量优先的并行收集器
并行收集器主要以到达一定的吞吐量为目标,适用于后台处理
响应时间优先的并发收集器
并发收集器主要是保证系统的响应时间,减少垃圾收集时的停顿时间。适用于应用服务器、电信领域等。
***年轻代大小选择
响应时间优先的应用:尽可能设置大,直到接近系统的最低响应时间限制(根据实际情况选择)。在此种情况下,年轻代收集发生的频率也是最小的。同时减少到达年老代的对象。
吞吐量优先的应用:尽可能的设置大,可能到达Gbit的成都,因为对响应时间没有要求,垃圾收集可以并行进行,一般适合8核CPU以上应用。
***年老代大小选择
响应时间优先的应用:年老代使用并发收集器,所以其大小需要小心设置,一般要考虑并发会话率和会话持续时间等一些参数。如果堆设置小了,可能会造成内存碎片、高回收频率以及应用暂停而使用传统的标记清除方式;如果堆大了,则需要较长的收集时间。最优化的方案,一般需要参考一下数据获得:
1、并发垃圾收集信息
2、持久代并发收集次数
3、传统GC信息
4、花在年轻代和年老代回收上的时间比例减少年轻代和年老代花费的时间,一般会提高应用的效率
***吞吐量优先的应用
一般吞吐量优先的应用都有一个很大的年轻代和一个较小的年老代。原因是,这样可以尽可能回收掉大部分短期对象,减少中期对象,而年老代尽存放长期存活的对象
***较小堆引起的碎片问题
因为年老代的并发收集器使用标记、清除算法,所以不会对堆进行压缩。当收集器回收时,他会把相邻的空间进行合并,这样可以分配给较大的对象。但是当堆空间较小时,运行一段时间以后,就会出现“碎片”,如果并发收集器找不到足够的空间,那么并发收集器将会停止,然后使用传统的标记、清除方式进行回收。如果出现“碎片”,可能需要进行如下配置:
Jc***ole,jProfile,VisualVM
Jc***ole:jdk自带, 功能简单,但是可以再系统有一定负荷的情况下使用,对垃圾回收算法有很详细的跟踪。
JProfiler:商业软件,需要付费,但是功能强大
VisualVM:JDK自带,功能强大,与Jprofiler类似,推荐
观察内存释放情况、集合类检查,对象树
上面这些调优工具都提供了强大的功能,但是总的来说一般分为以下几类功能:
一般就是根据垃圾回收前后情况对比,同时根据对象引用情况( 常见的集合对象引用 )分析,基本都可以找到泄漏点。
持久代沾满处理:
1、-XX:MaxPermSize=16m
2、换JDK比如:JRocket
系统内存被沾满:
一般是因为没有足够的资源产生线程造成的,系统创建线程时,除了要在Java堆中分配内存外,操作系统本身也需要分配资源来创建线程。因此,当线程数量大的一定程度以后,堆中或许还有空间,但是操作系统分配不出资源来了,出现异常。
分配给Java虚拟机的内存越多,系统剩余的资源就越少,因此,当系统内存固定时,分配给Java虚拟机的内存越多,那么,系统总共能够产生的线程也就越少,两者成反比。同事,可以通过修改-Xss来减少分配给单个线程的空间,也可以增加系统总共生产的线程数。
java程序内存问题的诊断方法:
查看jmap的命令参数,帮助查看堆信息
GC调优配置参数
一、JVM调优主要是调整下面两个指标
1. 停顿时间 :垃圾收集器做垃圾回收中断应用执行的时间。 -XX:MaxGCPauseMillis
2. 吞吐量 :垃圾收集的时间和总时间的占比:1/(1+n),吞吐量计算公式为1-1/(1+n), 吞吐量越大,证明性能越好。 -XX:GCTimeRatio=n
二、GC调优步骤
1. 打印GC日志
-XX:+Print***etails -XX:+PrintGCTimeStamps -XX:+Print***ateStamps -Xloggc:./*****
Tomcat则直接加在J**A_OPTS变量里
* 分析日志得到关键性指标
* 分析GC原因,调优JVM参数(工具:gceasy,GCViewer)
2. GC常用参数
堆栈设置
-Xss:每个线程的栈大小
-Xms:初始堆大小,默认物理内存的1/64
-Xmx:最大堆大小,默认物理内存的1/4
-Xmn:新生代大小
-XX:NewSize:设置新生代初始大小
-XX:NewRatio:默认2,表示新生代占老年代的1/2,占整个堆内存的1/3
-XX:SurivivorRatio:默认8,表示一个survivor区占用1/8的Eden内存,即1/10的新生代内存
-XX:MetaspaceSize:设置元空间大小
-XX:MaxMetaspaceSize:设置元空间最大允许大小,默认不受限制,JVM Metaspace会进行动态扩展
垃圾回收统计信息
-XX:+PrintGC
-XX:+Print***etails
-XX:+PrintGCTimeStamps
-Xloggc:filename
收集器设置:
-XX:+UseSerialGC:设置串行收集器
-XX:+UseParallelGC:设置并行收集器
-XX:+UseParallelOldGC:老年代使用并行收集器
-XX:+UseParNewGC:在新生代使用并行收集器
-XX:+UseConcMarkSweepGC:设置CMS并行收集器
-XX:UseG1GC:设置G1收集器
并行收集器设置:
-XX:ParallelGCThreads:设置用于垃圾回收的线程数
-XX:MaxGCPauseMillis:设置并行收集最大暂停时间
-XX:GCTimeRatio:设置垃圾回收时间占程序运行时间的百分比
-XX:YongGenerationSizeIncrement:年轻代GC后扩容的比例,默认是20%
CMS收集器设置
-XX:+UseConcMarkSweepGC:设置CMS并发收集器
-XX:+CMSIncrementalMode:设置为增量模式。适用于单CPU情况
-XX:ParallelGCThreads:设置并发收集器的线程数
-XX:CMSFullGCsBeforeCompanction:设定进行多少次CMS垃圾回收后,进行一次内存压缩
-XX:+CMSClassUnloadingEnabled:允许对类元数据进行回收
-XX:UseCMSInitiatingOccupancyOnly:表示只在到达阈值的时候,才进行CMS回收
-XX:+CMSIncrementalMode:设置为增量模式,适用于单CPU情况
-XX:ParallelCMSThreads:设定CMS的线程数量
-XX:CMSInitiatingOccupancyFraction:设置CMS收集器在老年代空间被使用多少后触发
-XX:+UseCMSCompactAtFullConllection:设置CMS收集器在完成垃圾收集后是否要进行一次内存碎片的整理
G1收集器设置
-XX:+UseG1GC:使用G1收集器
-XX:ParallelGCThreads:设置并发收集器的线程数
-XX:G1HeapRegionSize:制定分区大小(1MB~32MB,必须是2的幂),默认将整个堆划分为2048个分区
-XX:GCTimeRatio:吞吐量大小,0-100的整数(默认9),值为n则系统将花费不超过1/(1+n)的时间用于垃圾回收
-XX:MaxGCPauseMillis:目标暂停时间(默认200ms)
-XX:G1NewSizePercent:新生代内存初始空间(默认堆的5%)
-XX:G1MaxNewSizePercent:新生代内存最大空间
-XX:TargetSurvivorRatio:Survivor填充容量(默认50%)
-XX:MaxTenuringThreshold:最大任期阈值(默认15%)
-XX:InitiatingHeapOccupancyPercen:老年代占空间超过整堆比IHOP阈值(默认45%),超过则进行混合收集
-XX:G1HeapWastePercent:堆废物百分比(默认5%)
Spark性能调优篇七之JVM相关参数调整
由于Spark程序是运行在JVM基础之上的,所以我们这一篇来讨论一下关于JVM的一些优化操作。在开始JVM调优操作之前,我们先通过一张图看一下JVM简单的内存划分情况。
关于JVM内存的深入知识在这里不赘述,请大家自行对相关知识进行补充。好,说回Spark,运行Spark作业的时候,JVM对会对Spark作业产生什么影响呢?答案很简单,如果数据量过大,一定会导致JVM内存不足。在Spark作业运行时,会创建出来大量的对象,每一次将对象放入JVM时,首先将创建的对象都放入到eden区域和其中一个survivor区域中;当eden区域和一个survivor区域放满了以后,这个时候会触发minor gc,把不再使用的对象全部清除,而剩余的对象放入另外一个servivor区域中。JVM中默认的eden,survivor1,survivor2的内存占比为8:1:1。当存活的对象在一个servivor中放不下的时候,就会将这些对象移动到老年代。如果JVM的内存不够大的话,就会频繁的触发minor gc,这样会导致一些短生命周期的对象进入到老年代,老年代的对象不断的囤积,最终触发full gc。一次full gc会使得所有其他程序暂停很长时间。最终严重影响我们的Spark的性能和运行速度。
基于以上原因, 我们的第一个JVM优化点就是降低cache操作的内存占比 ;
spark中,堆内存又被划分成了两块儿,一块儿是专门用来给RDD的cache、persist操作进行RDD数据缓存用的;另外一块儿,就是我们刚才所说的,用来给spark算子函数的运行使用的,存放函数中自己创建的对象。默认情况下,给RDD cache操作的内存占比是***,即60%的内存都给了cache操作了。但是问题是,如果某些情况下cache占用的内存并不需要占用那么大,这个时候可以将其内存占比适当降低。怎么判断在什么时候调整RDD cache的内存占用比呢?其实通过Spark监控平台就可以看到Spark作业的运行情况了,如果发现task频繁的gc,就可以去调整cache的内存占用比了。通过*****("*****","***")来设定。
我们第二个JVM优化点是 堆外内存和连接等待时长的调整 ;其实这两个参数主要是为了解决一些Spark作业运行时候出现的一些错误信息而进行调整的。下面我们来分别介绍一下这两个点。
1.堆外内存的调整
a) 问题提出
有时候,如果你的spark作业处理的数据量特别特别大,几亿数据量;然后spark作业一运行就会出现类似shuffle file cannot find,executor、task lost,out of memory(内存溢出)等这样的错误。这是因为可能是说executor的堆外内存不太够用,导致executor在运行的过程中,可能会内存溢出;然后可能导致后续的stage的task在运行的时候,可能要从一些executor中去拉取shuffle map output文件,但是executor可能已经挂掉了,关联的blockmanager也没有了;所以可能会报shuffle output file not found;resubmitting task;executor lost 这样的错误;最终导致spark作业彻底崩溃。
上述情况下,就可以去考虑调节一下executor的堆外内存。也许就可以避免报错;此外,有时,堆外内存调节的比较大的时候,对于性能来说,也会带来一定的提升。
b) 解决方案:
--conf **************=2048
在spark-submit脚本里面添加如上配置。默认情况下,这个堆外内存上限大概是300多M;我们通常项目中真正处理大数据的时候,这里都会出现问题导致spark作业反复崩溃无法运行;此时就会去调节这个参数,到至少1G或者更大的内存。通常这个参数调节上去以后,就会避免掉某些OOM的异常问题,同时呢,会让整体spark作业的性能,得到较大的提升。
2.连接等待时长的调整
a) 问题提出:
由于JVM内存过小,导致频繁的Minor gc,有时候更会触犯full gc,一旦出发full gc;此时所有程序暂停,导致无法建立网络连接;spark默认的网络连接的超时时长是60s;如果卡住60s都无法建立连接的话,那么就宣告失败了。碰到一种情况,有时候报错信息会出现一串类似file id not found,file lost的错误。这种情况下,很有可能是task需要处理的那份数据的executor在正在进行gc。所以拉取数据的时候,建立不了连接。然后超过默认60s以后,直接宣告失败。几次都拉取不到数据的话,可能会导致spark作业的崩溃。也可能会导致DAGScheduler,反复提交几次*****,反复提交几次task。大大延长我们的spark作业的运行时间。
b) 解决方案:
--conf *****=300
在spark-submit脚本中添加如上参数,调节这个值比较大以后,通常来说,可以避免部分的偶尔出现的某某文件拉取失败,某某文件lost掉的错误。
总结:本文关于JVM的相关调优暂时先到这里,关于Spark中的JVM相关知识后面会在trouble shutting的时候还会继续介绍。后续还会不断更新关于Spark作业优化的一些其他方式,欢迎关注。
z小赵 Spark性能调优之JVM相关参数调整
JVM常见的调优参数有哪些
-Xms256m:初始化堆大小为 256m;
-Xmx2g:堆最大内存为 2g;
-Xmn50m:新生代的大小50m;
-XX:+Print***etails 打印 gc 详细信息
-XX:+HeapDumpOnOutOfMemoryError 在发生OutOfMemoryError错误时,来dump堆快照
-XX:NewRatio=4 设置年轻的和老年代的内存比例为 1:4;
-XX:SurvivorRatio=8 设置新生代 Eden 和 Survivor 比例为 8:2;
//参数上写的,都是新生代的垃圾回收器
-XX:+UseSerialGC 新生代和老年代都用串行收集器 Serial + Serial Old
-XX:+UseParNewGC 指定使用 ParNew + Serial Old 垃圾回收器组合;
-XX:+UseParallelGC 新生代使用Parallel Scavenge,老年代使用Serial Oldujiuye
//参数上写的,都是老年代的垃圾回收器
-XX:+UseParallelOldGC:新生代ParallelScavenge + 老年代ParallelOld组合;
-XX:+UseConcMarkSweepGC:新生代使用ParNew,老年代的用CMS;
-XX:NewSize;新生代最小值;
-XX:MaxNewSize:新生代最大值
-XX:MetaspaceSize 元空间初始化大小
-XX:MaxMetaspaceSize 元空间最大值
jvm调优如何做
Jvm调优依次参考如下
如果没有必要,请不要做调优
如果没有必要,请不要做调优。没有万能的调优,只有根据使用场景选择合适的手段,初始默认指定堆大小,元空间大小(jdk8)即可
确认性能问题由JVM再考虑调优,如fullGC频繁,GC时间较长,内存使用不正常,OOM等。开启JVM监控,记录GC日志,分析GC情况
JVM调优的目标是减少/避免老年代GC
对于追求响应时间的如web系统使用并发垃圾回收器(jdk8开启G1,低版本使用CMS)
根据JVM内存使用情况,可以考虑手动设置年轻代大小,survivor区大小,减少/避免垃圾进入老年代(注意jdk8默认开启自适应调节,需关闭)
影响GC时间的还有GC线程数等等,需要结合GC日志分析GC过程可能存在的问题
jvm性能调优都做了什么
JVM是最好的软件工程之一,它为Java提供了坚实的基础,许多流行语言如Kotlin、Scala、Clojure、Groovy都使用JVM作为运行基础。一个专业的Java工程师必须要了解并掌握JVM,接下来就给大家分享Java基础知识中JVM调优相关知识点。
杭州Java基础知识学习之JVM调优讲解
JVM常见的调优参数包括:
-Xmx:指定java程序的最大堆内存, 使用java -Xmx5000M -version判断当前系统能分配的最大堆内存;
-Xms:指定最小堆内存, 通常设置成跟最大堆内存一样,减少GC;
-Xmn:设置年轻代大小。整个堆大小=年轻代大小+年老代大小。所以增大年轻代后,将会减小年老代大小。此值对系统性能影响较大,Sun官方推荐配置为整个堆的3/8;
-Xss:指定线程的最大栈空间, 此参数决定了java函数调用的深度, 值越大调用深度越深, 若值太小则容易出栈溢出错误(StackOverflowError);
-XX:PermSize:指定方法区(永久区)的初始值,默认是物理内存的1/64,在Java8永久区移除, 代之的是元数据区,由-XX:MetaspaceSize指定;
-XX:MaxPermSize:指定方法区的最大值, 默认是物理内存的1/4,在java8中由-XX:MaxMetaspaceSize指定元数据区的大小;
-XX:NewRatio=n:年老代与年轻代的比值,-XX:NewRatio=2, 表示年老代与年轻代的比值为2:1;
-XX:SurvivorRatio=n:Eden区与Survivor区的大小比值,-XX:SurvivorRatio=8表示Eden区与Survivor区的大小比值是8:1:1,因为Survivor区有两个(from, to)。
JVM实质上分为三大块,年轻代(YoungGen),年老代(Old Memory),及持久代(Perm,在Java8中被取消)。
年轻代大小选择
响应时间优先的应用:尽可能设大,直到接近系统的最低响应时间限制(根据实际情况选择)。在此种情况下,年轻代收集发生的频率也是最小的。同时,减少到达年老代的对象。
吞吐量优先的应用:尽可能的设置大,可能到达Gbit的程度。因为对响应时间没有要求,垃圾收集可以并行进行,一般适合8CPU以上的应用。
年老代大小选择
响应时间优先的应用:年老代使用并发收集器,所以其大小需要小心设置,一般要考虑并发会话率和会话持续时间等一些参数。如果堆设置小了,可以会造成内存碎片、高回收频率以及应用暂停而使用传统的标记清除方式;如果堆大了,则需要较长的收集时间。最优化的方案,一般需要参考以下数据获得:并发垃圾收集信息、持久代并发收集次数、传统GC信息、花在年轻代和年老代回收上的时间比例。
减少年轻代和年老代花费的时间,一般会提高应用的效率。
吞吐量优先的应用:一般吞吐量优先的应用都有一个很大的年轻代和一个较小的年老代。原因是,这样可以尽可能回收掉大部分短期对象,减少中期的对象,而年老代尽存放长期存活对象。
较小堆引起的碎片问题
因为年老代的并发收集器使用标记、清除算法,所以不会对堆进行压缩。当收集器回收时,他会把相邻的空间进行合并,这样可以分配给较大的对象。但是,当堆空间较小时,运行一段时间以后,就会出现“碎片”,如果并发收集器找不到足够的空间,那么并发收集器将会停止,然后使用传统的标记、清除方式进行回收。如果出现“碎片”,可能需要进行如下配置:
-XX:+UseCMSCompactAtFullCollection:使用并发收集器时,开启对年老代的压缩。
-XX:CMSFullGCsBeforeCompaction=0:上面配置开启的情况下,这里设置多少次Full GC后,对年老代进行压缩。
更多文章:
sort命令的具体使用方法(linux sort 命令整理)
2026年4月30日 14:40
vscode输入了代码怎么运行(visual studio code怎么运行代码)
2026年4月30日 14:00
不是jquery的选择器(jquery的核心功能不是根据选择器查找HTML元素然后对元素执行相应操作这句话是对是错 )
2026年4月30日 13:20
c语言随机产生0 10的整数(c语言:随机产生的100个0到10之间的整数,设计程序,统计0到10的个数)
2026年4月30日 12:40
matlab的imwrite函数(matlab如何用out输出图像)
2026年4月30日 12:20
insert all(在Oracle中,通过一个INSERT ALL语句批量插入数据)
2026年4月30日 12:00
oracle建库步骤(在命令行如何创建oracle实例与数据库,需要详细点教程,谢谢)
2026年4月30日 11:40



