java虚拟机的调优(java虚拟机如何调优)
华为云服务器特价优惠火热进行中! 2核2G2兆仅需 38 元;4核4G3兆仅需 79 元。购买时间越长越优惠!更多配置及优惠价格请咨询客服。
合作流程: |
本篇文章给大家谈谈java虚拟机的调优,以及java虚拟机如何调优对应的知识点,希望对各位有所帮助,不要忘了收藏本站喔。
微信号:cloud7591如需了解更多,欢迎添加客服微信咨询。
复制微信号
本文目录一览:
JVM性能调优-G1
本篇是对Java官网G1收集器调优的精简版。针对G1垃圾的收集阶段可能出现的问题,非合理内存分配,大对象占用,Full GC等问题作出解决方式和操作参数。
G1是一个吞吐量和时间延迟之间相互平衡的收集器。目标是高吞吐量下提供相对较小、统一的暂停。
所以如果是交互性强的应用程序,使用G1时需要基于时延优先进行考虑。
虚拟机从操作系统内存中分配或归还内存可能会导致不必要的延迟。通过使用选项-Xms和-Xmx将最小和最大堆大小设置为相同的值,并使用 - XX:+AlwaysPreTouch 预触摸所有内存,以将这项工作移到VM启动阶段,从而避免延迟。
并行处理 Reference对象,ParallelRefProcEnabled默认值false,若 GC log 里出现 Reference 处理时间较长的日志,可以开启此参数- XX:+ParalleRefProcEnabled 。开启后会使用jvm可用的线程数进行处理,但官网上提到的-XX:ReferencesPerThread参数在jdk17的版本中没有找到,猜测可能是jvm内部控制不再作可调试的参数。
年轻代收集所花费的时间大致与年轻代的大小成正比。官网给出的两个参数- XX:G1NewSizePercent ,-XX: G1MaxNewSizePercent 在jdk17中没有找到,在没有固定年轻代大小时,G1会进行动态调整,所以这个调优的参考性不大,可以忽略。
减少老年代regions暂停时间
RS是一个抽象的数据结构,具体的实现由table card完成。一般会把记忆集和卡表放在一起讨论。简单来讲就是所有对象引用关系的一个集合,GCRoot时扫描的不是去实际的内存区域,否则跨代引用时从新生代到老年代会是一个漫长的过程。RS很好的解决了跨代引用的问题。由于RS会动态更新,垃圾收集必须先等RS更新完毕后才去执行。所以RS更新如果耗时过长则会影响回收时间。
RS的大小跟堆空间是成正比的。
扫描RS时间也由G1为保持低存储容量而执行的压缩量决定。记忆的集合存储在内存中越紧凑,在垃圾收集期间检索存储的值所花费的时间就越多。G1自动执行这种压缩,称为记忆集粗化,同时根据该区域记忆集的当前大小更新记忆集。特别是在最高压缩级别时,检索实际数据可能非常慢。
使用选项- XX:G1SummarizeRSetStatsPeriod 结合gc+remset=trace级别日志显示是否发生粗化。
解决方案
操作选项
为本地IDE运行设置JVM启动参数调优
本次通过 VisulVm 进行线程的堆区观察,关于在应用运行时,所占用内存发生OOM
切换到JDK的bin目录下,调查堆是否发生OOM
console : java -XX:+PrintCommandLineFlags -version
Output
这里显示 堆的最大值大小为 MaxHeapSize ,这里的MaxHeapSize可能和VisulVm中堆的最大值有所偏差,
这是因为 虚拟机的内存对齐 ,我们暂时以控制台显示的最大堆值为标准,对比VisulVm中观察到的堆内存大小
上图可以看出来为最大堆为 2124414976B ,从2:30开始出现内存抖动。怀疑是因为在jvm启动时,
没有设置年轻代和老年代的分配比例,导致年轻代被频繁GC,故在idea的 VM OPTIONS 中设置
-XX:NewRatio=2
可以看到从2:30之后,内存的增长速度趋于平缓,可以看出没有发生频繁GC
但系统仍然被占用较大的内存,继续分析idea所属进程
发现idea进程中占用最多的是idea程序本身的内存,尝试设置运行时最大堆的上限
VM OPTIONS : -XX:NewRatio=2 -XX:+HeapDumpOnOutOfMemoryError -Xmx1024m -Xms1024m -XX:HeapDumpPath=d:\dump
VisulVM显示如下图
可以看到虽然设置了最大堆上限为默认的1024mb,但是内存增长的速度依然很快
比较初始化堆的峰值,即图三中一开始出现堆内存峰值的时间点 分配: 116916114b = 115MB
考虑到除了java堆之外,可能还有其它区域占用内存空间,见 深入理解java虚拟机
VM OPTIONS 设置为 -XX:NewRatio=2 -XX:+HeapDumpOnOutOfMemoryError -Xmx1024m -Xms130m -XX:HeapDumpPath=d:\dump
ps:为什么考虑到需要调节初始化堆的大小呢?
让我们呢看一看目录下输出的日志文件
hs_err_pid13036.log
建议大家对于当前测试线程不清楚的时候可以多是实在jvm启动参数里设置OOM的输出日志文件,以便于查找错误
但这只是简单的分配年轻代和老年代,那有没有适合分代的回收调参呢
根据本机8G双核的机器配置,采用Parnew+cms收集器,年轻代加快复制次数,老年代减少停顿时间。idea最终调优如下
更大型系统的jvm调优请参考 大型跨境电商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系统,3.5G物理内存,JDK5.0下测试,最大设置为1478m。
典型设置:
JVM给了三种选择:串行收集器,并行收集器,并发收集器,但是串行收集器只适用于小数据量的情况,一般不考虑使用了,所以这里只针对并行收集器和并发收集器。默认情况下,JDK5.0以前是使用的串行收集器,如果想使用其他收集器需要在启动时加入相应的参数, JDK5.0以后,JVM会根据系统当前的配置进行判断
吞吐量优先的并行收集器
并行收集器主要以到达一定的吞吐量为目标,适用于后台处理
响应时间优先的并发收集器
并发收集器主要是保证系统的响应时间,减少垃圾收集时的停顿时间。适用于应用服务器、电信领域等。
6.1年轻代大小选择
响应时间优先的应用:尽可能设置大,直到接近系统的最低响应时间限制(根据实际情况选择)。在此种情况下,年轻代收集发生的频率也是最小的。同时减少到达年老代的对象。
吞吐量优先的应用:尽可能的设置大,可能到达Gbit的成都,因为对响应时间没有要求,垃圾收集可以并行进行,一般适合8核CPU以上应用。
6.2年老代大小选择
响应时间优先的应用:年老代使用并发收集器,所以其大小需要小心设置,一般要考虑并发会话率和会话持续时间等一些参数。如果堆设置小了,可能会造成内存碎片、高回收频率以及应用暂停而使用传统的标记清除方式;如果堆大了,则需要较长的收集时间。最优化的方案,一般需要参考一下数据获得:
1、并发垃圾收集信息
2、持久代并发收集次数
3、传统GC信息
4、花在年轻代和年老代回收上的时间比例减少年轻代和年老代花费的时间,一般会提高应用的效率
6.3吞吐量优先的应用
一般吞吐量优先的应用都有一个很大的年轻代和一个较小的年老代。原因是,这样可以尽可能回收掉大部分短期对象,减少中期对象,而年老代尽存放长期存活的对象
6.4较小堆引起的碎片问题
因为年老代的并发收集器使用标记、清除算法,所以不会对堆进行压缩。当收集器回收时,他会把相邻的空间进行合并,这样可以分配给较大的对象。但是当堆空间较小时,运行一段时间以后,就会出现“碎片”,如果并发收集器找不到足够的空间,那么并发收集器将会停止,然后使用传统的标记、清除方式进行回收。如果出现“碎片”,可能需要进行如下配置:
Jconsole,jProfile,VisualVM
Jconsole:jdk自带, 功能简单,但是可以再系统有一定负荷的情况下使用,对垃圾回收算法有很详细的跟踪。
JProfiler:商业软件,需要付费,但是功能强大
VisualVM:JDK自带,功能强大,与Jprofiler类似,推荐
观察内存释放情况、集合类检查,对象树
上面这些调优工具都提供了强大的功能,但是总的来说一般分为以下几类功能:
一般就是根据垃圾回收前后情况对比,同时根据对象引用情况( 常见的集合对象引用 )分析,基本都可以找到泄漏点。
持久代沾满处理:
1、-XX:MaxPermSize=16m
2、换JDK比如:JRocket
系统内存被沾满:
一般是因为没有足够的资源产生线程造成的,系统创建线程时,除了要在Java堆中分配内存外,操作系统本身也需要分配资源来创建线程。因此,当线程数量大的一定程度以后,堆中或许还有空间,但是操作系统分配不出资源来了,出现异常。
分配给Java虚拟机的内存越多,系统剩余的资源就越少,因此,当系统内存固定时,分配给Java虚拟机的内存越多,那么,系统总共能够产生的线程也就越少,两者成反比。同事,可以通过修改-Xss来减少分配给单个线程的空间,也可以增加系统总共生产的线程数。
java程序内存问题的诊断方法:
查看jmap的命令参数,帮助查看堆信息
关于java虚拟机的调优和java虚拟机如何调优的介绍到此就结束了,不知道你从中找到你需要的信息了吗 ?如果你还想了解更多这方面的信息,记得收藏关注本站。
