本文目录一览:
- 1、JVM调优-Xms -Xmx -Xmn -Xss
- 2、启动JAVA程序时,参数-Xms及Xmx有什么用
- 3、JVM内存设置多大合适?Xmx和Xmn如何设置?
- 4、JVM调优,S区太小导致FGC频繁
- 5、2018-08-30 Xms/Xmx/Xmn/Xss区别
JVM调优-Xms -Xmx -Xmn -Xss
Xmn、Xms、Xmx、Xss都是JVM对内存的配置参数,我们可以根据不同需要区修改这些参数,以达到运行程序的最好效果。
尽可能设大,直到接近系统的最低响应时间限制(根据实际情况选择)。在此种情况下,年轻代收集发生的频率也是最小的。同时,减少到达年老代的对象。
年老代使用并发收集器,所以其大小需要小心设置,一般要考虑并发会话率和会话持续时间等一些参数。如果堆设置小了,可以会造成内存碎片、高回收频率以及应用暂停而使用传统的标记清除方式;如果堆大了,则需要较长的收集时间。
最优化的方案,一般需要参考以下数据获得:
减少年轻代和年老代花费的时间,一般会提高应用的效率
尽可能的设置大,可能到达Gbit的程度。因为对响应时间没有要求,垃圾收集可以并行进行,一般适合8CPU以上的应用。
一般吞吐量优先的应用都有一个很大的年轻代和一个较小的年老代。原因是,这样可以尽可能回收掉大部分短期对象,减少中期的对象,而年老代尽存放长期存活对象。
启动JAVA程序时,参数-Xms及Xmx有什么用
个人之见,欢迎指正:
Xmx是java的一个选项,用来设置你的应用程序能够使用的最大内存数(看好,致使你的应用程序,不是整个jvm),如果你的程序要花很大内存的话,那就需要修改缺省的设置,比如配置tomcat的时候,如果流量啊程序啊都很大的话就需要加大这个值了,不过有一点是要记住的,不要大得超过你的机器的内存,那样你的机器会受不了的,到时候就死翘翘了。
Xms是另一个设置内存的参数,用它来设置程序初始化的时候内存栈的大小,增加这个值的话你的程序的启动性能会得到提高。不过同样有前面的限制,以及受到xmx的限制。
另外,一个操作系统通常都只使用jvm,这就是你说的“运行在同一个JVM中的程序”,不同的虚拟机的实现虽然千差万别,但是他们的运行模式都是一样的,只是性能有所不同罢了。
JVM内存设置多大合适?Xmx和Xmn如何设置?
问题:
新上线一个java服务,或者是RPC或者是WEB站点, 内存的设置该怎么设置呢?设置成多大比较合适,既不浪费内存,又不影响性能呢?
分析:
依据的原则是根据Java Performance里面的推荐公式来进行设置。
具体来讲:
Java整个堆大小设置,Xmx 和 Xms设置为老年代存活对象的3-4倍,即FullGC之后的老年代内存占用的3-4倍
永久代 PermSize和MaxPermSize设置为老年代存活对象的1.2-1.5倍。
年轻代Xmn的设置为老年代存活对象的1-1.5倍。
老年代的内存大小设置为老年代存活对象的2-3倍。
BTW:
1、Sun官方建议年轻代的大小为整个堆的3/8左右, 所以按照上述设置的方式,基本符合Sun的建议。
2、堆大小=年轻代大小+年老代大小, 即xmx=xmn+老年代大小 。 Permsize不影响堆大小。
3、为什么要按照上面的来进行设置呢? 没有具体的说明,但应该是根据多种调优之后得出的一个结论。
如何确认老年代存活对象大小?
方式1(推荐/比较稳妥):
JVM参数中添加GC日志,GC日志中会记录每次FullGC之后各代的内存大小,观察老年代GC之后的空间大小。可观察一段时间内(比如2天)的FullGC之后的内存情况,根据多次的FullGC之后的老年代的空间大小数据来预估FullGC之后老年代的存活对象大小(可根据多次FullGC之后的内存大小取平均值)
方式2:(强制触发FullGC, 会影响线上服务,慎用)
方式1的方式比较可行,但需要更改JVM参数,并分析日志。同时,在使用CMS回收器的时候,有可能不能触发FullGC(只发生CMS GC),所以日志中并没有记录FullGC的日志。在分析的时候就比较难处理。
BTW:使用jstat -gcutil工具来看FullGC的时候, CMS GC是会造成2次的FullGC次数增加。 具体可参见之前写的一篇关于jstat使用的文章
所以,有时候需要强制触发一次FullGC,来观察FullGC之后的老年代存活对象大小。
注:强制触发FullGC,会造成线上服务停顿(STW),要谨慎,建议的操作方式为,在强制FullGC前先把服务节点摘除,FullGC之后再将服务挂回可用节点,对外提供服务
在不同时间段触发FullGC,根据多次FullGC之后的老年代内存情况来预估FullGC之后的老年代存活对象大小
如何触发FullGC ?
使用jmap工具可触发FullGC
jmap -dump:live,format=b,file=heap.bin pid 将当前的存活对象dump到文件,此时会触发FullGC
jmap -histo:live pid 打印每个class的实例数目,内存占用,类全名信息.live子参数加上后,只统计活的对象数量. 此时会触发FullGC
具体操作实例:
以我司的一个RPC服务为例。
BTW:刚上线的新服务,不知道该设置多大的内存的时候,可以先多设置一点内存,然后根据GC之后的情况来进行分析。
初始JVM内存参数设置为: Xmx=2G Xms=2G xmn=1G
使用jstat 查看当前的GC情况。如下图:
YGC平均耗时: 173.825s/15799=11ms
FGC平均耗时:0.817s/41=19.9ms
平均大约10-20s会产生一次YGC
看起来似乎不错,YGC触发的频率不高,FGC的耗时也不高,但这样的内存设置是不是有些浪费呢?
为了快速看数据,我们使用了方式2,产生了几次FullGC,FullGC之后,使用的jmap -heap 来看的当前的堆内存情况(也可以根据GC日志来看)
heap情况如下图:(命令 : jmap -heap pid)
上图中的concurrent mark-sweep generation即为老年代的内存描述。
老年代的内存占用为100M左右。 按照整个堆大小是老年代(FullGC)之后的3-4倍计算的话,设置各代的内存情况如下:
Xmx=512m Xms=512m Xmn=128m PermSize=128m 老年代的大小为 (512-128=384m)为老年代存活对象大小的3倍左右
调整之后的,heap情况
GC情况如下:
YGC 差不多在10s左右触发一次。每次YGC平均耗时大约9.41ms。可接受。
FGC平均耗时:0.016s/2=8ms
整体的GC耗时减少。但GC频率比之前的2G时的要多了一些。
注: 看上述GC的时候,发现YGC的次数突然会增多很多个,比如 从1359次到了1364次。具体原因是?
总结:
在内存相对紧张的情况下,可以按照上述的方式来进行内存的调优, 找到一个在GC频率和GC耗时上都可接受的一个内存设置,可以用较小的内存满足当前的服务需要
但当内存相对宽裕的时候,可以相对给服务多增加一点内存,可以减少GC的频率,GC的耗时相应会增加一些。 一般要求低延时的可以考虑多设置一点内存, 对延时要求不高的,可以按照上述方式设置较小内存。
补充:
永久代(方法区)并不在堆内,所以之前有看过一篇文章中描述的 整个堆大小=年轻代+年老代+永久代的描述是不正确的。
转自:
-verbose:gc 现实垃圾收集信息
-Xloggc:gc.log 指定垃圾收集日志文件
-Xmn:young generation的heap大小,一般设置为Xmx的3、4分之一
-XX:SurvivorRatio=2 :生还者池的大小,默认是2,如果垃圾回收变成了瓶颈,您可以尝试定制生成池设置
-XX:NewSize: 新生成的池的初始大小。 缺省值为2M。
-XX:MaxNewSize: 新生成的池的最大大小。 缺省值为32M。
+XX:AggressiveHeap 会使得 Xms没有意义。这个参数让jvm忽略Xmx参数,疯狂地吃完一个G物理内存,再吃尽一个G的swap。
-Xss:每个线程的Stack大小,“-Xss 15120” 这使得JBoss每增加一个线程(thread)就会立即消耗15M内存,而最佳值应该是128K,默认值好像是512k.
JVM调优,S区太小导致FGC频繁
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后,对年老代进行压缩。
2018-08-30 Xms/Xmx/Xmn/Xss区别
Xms 是指设定程序启动时占用内存大小。一般来讲,大点,程序会启动的快一点,但是也可能会导致机器暂时间变慢。
Xmx 是指设定程序运行期间最大可占用的内存大小。如果程序运行需要占用更多的内存,超出了这个设置值,就会抛出OutOfMemory异常。
Xmn 是指年轻代大小。( 整个堆大小=年轻代大小 + 年老代大小 + 持久代大小 。持久代一般固定大小为64m,所以增大年轻代后,将会减小年老代大小。此值对系统性能影响较大,Sun官方推荐配置为整个堆的3/8。)
Xss 是指设定每个线程的堆栈大小。这个就要依据你的程序,看一个线程大约需要占用多少内存,可能会有多少线程同时运行等
-Xms :初始堆大小
-Xmx :最大堆大小
-XX:NewSize=n :设置年轻代大小(Xmn)
-XX:NewRatio=n: 设置年轻代和年老代的比值。如:为3,表示年轻代与年老代比值为1:3,年轻代占整个年轻代年老代和的1/4
-XX:SurvivorRatio=n :年轻代中Eden区与两个Survivor区的比值。注意Survivor区有两个。如:3,表示Eden:Survivor=3:2,一个Survivor区占整个年轻代的1/5
-XX:MaxPermSize=n :设置持久代大小
堆的内存分配用-Xms和-Xmx
-Xms分配堆最小内存,默认为物理内存的1/64;-Xmx分配最大内存,默认为物理内存的1/4。
非堆内存分配用-XX:PermSize和-XX:MaxPermSize
-XX:PermSize分配非堆最小内存,默认为物理内存的1/64;-XX:MaxPermSize分配最大内存,默认为物理内存的1/4。