一、JVM参数
-X参数:JVM的非标准参数,不同版本参数不同,可通过 java -X 查看
-XX参数:-XX+:开启某个属性 -XX-:关闭某个属性 -XX:key=value设置值
1.基础参数
参数名称 | 含义 | 默认值 |
|
-Xms | 初始堆大小 等价于-XX:InitialHeapSize | 物理内存的1/64 | 空余堆内存小于40%时,JVM就会增大堆直到-Xmx的最大限制.默认(MinHeapFreeRatio参数可以调整) |
-Xmx | 最大堆大小 等价于-XX:MaxHeapSize | 物理内存的1/4 | 空余堆内存大于70%时,JVM会减少堆直到 -Xms的最小限制默认(MaxHeapFreeRatio参数可以调整) |
-XX:MinHeapFreeRatio | 堆在使用率小于n的情况下,进行收缩 | Xms=Xmx情况下无效 | |
-XX:MaxHeapFreeRatio | 堆在使用率大于n的情况下,进行扩张 | Xms=Xmx情况下无效 | |
-Xss | 每个线程的堆栈大小 | -Xss | JDK5.0以后每个线程堆栈大小为1M,以前每个线程堆栈大小为256K. |
-Xmn | 年轻代大小 (eden+ 2 survivor space) (1.4or later) |
| 整个堆大小=年轻代大小 + 年老代大小 + 持久代大小. 增大年轻代后,将会减小年老代大小.此值对系统性能影响较大,Sun官方推荐配置为整个堆的3/8 |
-XX:NewSize | 设置年轻代大小(for 1.3/1.4) |
|
|
-XX:MaxNewSize | 年轻代最大值(for 1.3/1.4) |
|
|
-XX:PermSize | 设置持久代初始值 | 物理内存的1/64 |
|
-XX:MaxPermSize | 设置持久代最大值 | 物理内存的1/4 |
|
-XX:MetaspaceSize=128m | 元空间大小 |
|
|
-XX:MaxMetaspaceSize | 最大元空间大小 |
|
|
-XX:ThreadStackSize | 线程栈大小 |
|
|
-XX:NewRatio | 年轻代(包括Eden和两个Survivor区)与年老代的比值(除去持久代) |
|
- |
-XX:SurvivorRatio | Eden区与Survivor区的大小比值 |
| =8,则两个Survivor区与一个Eden区的比值为2:8,一个Survivor区占整个年轻代的1/10 |
-XX:+UseFastAccessorMethods | 原始类型的快速优化 |
|
|
-XX:+DisableExplicitGC | 关闭System.gc() |
| 这个参数需要严格的测试 |
-XX:MaxTenuringThreshold | 进入老年代阈值设置 | 默认15 | 该参数只有在串行GC时才有效. |
-Xnoclassgc | 禁用垃圾回收 |
|
|
-XX:PretenureSizeThreshold | 对象超过多大是直接在旧生代分配 | 0,不管多大,都先在Eden区分配 |
|
-XX:+CollectGen0First | FullGC时是否先YGC | false |
|
-XX:SoftRefLRUPolicyMSPerMB | 每兆堆空闲空间中SoftReference的存活时间
| 1s |
|
2.并行收集器相关参数
-XX:+UseParallelGC | GC采用parallel MSC |
| 选择垃圾收集器为并行收集器.此配置仅对年轻代有效. |
-XX:+UseParNewGC | 设置年轻代为并行收集 |
| 可与CMS收集同时使用 |
-XX:ParallelGCThreads | 并行收集器的线程数 |
| 此值最好配置与处理器数目相等 同样适用于CMS |
-XX:+UseParallelOldGC | 年老代垃圾收集方式为并行收集(Parallel Compacting) |
| 这个是JAVA 6出现的参数选项 |
-XX:MaxGCPauseMillis | 每次年轻代垃圾回收的最长时间(最大暂停时间) |
| 如果无法满足此时间,JVM会自动调整年轻代大小,以满足此值. |
-XX:+UseAdaptiveSizePolicy | 自动选择年轻代区大小和相应的Survivor区比例 |
| 设置此选项后,并行收集器会自动选择年轻代区大小和相应的Survivor区比例,以达到目标系统规定的最低相应时间或者收集频率等,此值建议使用并行收集器时,一直打开. |
-XX:GCTimeRatio | 设置垃圾回收时间占程序运行时间的百分比 |
| 公式为1/(1+n) |
-XX:+ScavengeBeforeFullGC | Full GC前调用YGC | true |
|
-XX:+UseCMSCompactAtFullCollection | 使用并行收集器时,开启对老年代的压缩 |
|
|
-XX:+UseCompressedClassPointers | 类指针压缩 |
|
|
3.CMS相关参数
-XX:+UseConcMarkSweepGC | 使用CMS内存收集 |
|
|
-XX:CMSFullGCsBeforeCompaction | 运行多少次GC以后对内存空间进行压缩,整理. |
| 并发收集器不对内存空间进行压缩,整理,所以运行一段时间以后会产生"碎片",使得运行效率降低. |
-XX:+CMSParallelRemarkEnabled | 降低标记停顿 |
|
|
-XX+UseCMSCompactAtFullCollection | 在FULL GC的时候, 对年老代的压缩 |
| CMS是不会移动内存的, 因此, 这个非常容易产生碎片, 导致内存不够用, 因此, 内存的压缩这个时候就会被启用。 |
-XX:+UseCMSInitiatingOccupancyOnly | 使用手动定义初始化定义开始CMS收集 |
| 禁止hostspot自行触发CMS GC |
-XX:CMSInitiatingOccupancyFraction=70 | 使用cms作为垃圾回收 使用70%后开始CMS收集 | 92 |
|
-XX:CMSInitiatingPermOccupancyFraction | 设置Perm Gen使用到达多少比率时触发 | 92 |
|
-XX:+CMSClassUnloadingEnabled |
|
|
|
4.辅助信息
-XX:+PrintGC |
| 输出形式: [GC 118250K->113543K(130112K), 0.0094143 secs] [Full GC 121376K->10414K(130112K), 0.0650971 secs] |
-XX:+PrintGCDetails |
| 输出形式:[GC [DefNew: 8614K->781K(9088K), 0.0123035 secs] 118250K->113543K(130112K), 0.0124633 secs] [GC [DefNew: 8614K->8614K(9088K), 0.0000665 secs][Tenured: 112761K->10414K(121024K), 0.0433488 secs] 121376K->10414K(130112K), 0.0436268 secs] |
-XX:+PrintGCTimeStamps |
|
|
-XX:+PrintGC:PrintGCTimeStamps |
| 可与-XX:+PrintGC -XX:+PrintGCDetails混合使用 输出形式:11.851: [GC 98328K->93620K(130112K), 0.0082960 secs] |
-XX:+PrintGCApplicationStoppedTime | 打印垃圾回收期间程序暂停的时间.可与上面混合使用 | 输出形式:Total time for which application threads were stopped: 0.0468229 seconds |
-XX:+PrintGCApplicationConcurrentTime | 打印每次垃圾回收前,程序未中断的执行时间.可与上面混合使用 | 输出形式:Application time: 0.5291524 seconds |
-XX:+PrintHeapAtGC | 打印GC前后的详细堆栈信息 |
|
-Xloggc:filename | 把相关日志信息记录到文件以便分析. 与上面几个配合使用 |
|
-XX:+PrintClassHistogram | garbage collects before printing the histogram. |
|
XX:+PrintTenuringDistribution | 查看每次minor GC后新的存活周期的阈值 |
|
二、CMS和G1
1.CMS(Concurrent Mark Sweep)
是一种以获取最短回收停顿时间为目标的收集器。因为CMS收集器工作时,GC工作线程与用户线程可以并发执行,以此来达到降低收集停顿时间的目的。
CMS仅作用于老年代的收集,是基于“标记-清除”算法的;
-
初始标记:需要暂停所有其他线程(Stop-The-World),仅仅标记GC Roots能直接关联到的对象,速度很快
-
并发标记:可以和用户线程并发执行,通过GCRoots Tracing 标记所有可达对象;
-
重新标记:stop-the-world, 对并发标记阶段用户线程运行产生的垃圾对象进行标记修正,以及更新逃逸对象;
-
并发清除:可以和用户线程并发执行,清理在重复标记中被标记为可回收的对象。
优点:
-
支持并发收集;
-
低停顿,CMS可以控制将耗时的两个stop-the-world操作与用户线程恰当的时机并发执行,并且能保证在段时间执行完成
缺点:
-
对CPU资源非常敏感;在并发阶段虽然不会导致用户线程停顿,但是会因为占用了一部分CPU资源,如果在CPU资源不足的情况下应用会有明显的卡顿。
-
无法处理浮动垃圾:在执行‘并发清理’步骤时,用户线程也会同时产生一部分可回收对象,但是这部分可回收对象只能在下次执行清理是才会被回收。
-
CMS是基于“标记-清除”算法实现的收集器,收集结束后会有大量空间碎片产生;
适用场景:低停顿,在老年代不频繁GC的场景下,比较适用;比如互联网站或B/S系统的服务器上;
CMS出现fullGC的原因:
-
年轻代晋升到老年代没有足够的连续空间,很有可能是内存碎片导致的,会触发FullGC;
-
在并发过程中,JVM觉得在并发过程结束之前堆就会满,需要提前触发FullGC
2. G1收集器(java9的默认收集器)
G1收集器将整个Java堆划分为多个大小相等的独立区域(Region),虽然还保留有新生代和老年代的概念,但新生代和老年代不再是物理隔离的了,它们都是一部分Region(不需要连续)的集合。Region的大小是一致的,数值是在1M到32M字节之间的一个2的幂值数,JVM会尽量划分2048个左右、同等大小的Region。
如果一个对象占用的空间超过了分区容量50%以上,G1收集器就认为这是一个巨型对象。这些巨型对象,默认直接会被分配在年老代,但是如果它是一个短期存在的巨型对象,就会对垃圾收集器造成负面影响。
G1特点:
-
并行与并发:G1能充分利用多CPU、多核环境下的硬件优势,使用多个CPU来缩短停顿时间,部分其他收集器原来需要停顿Java线程执行的GC操作,G1收集器仍然可以通过并发的方式让Java程序继续运行;
-
分代收集:能够采用不同的方式去处理新创建的对象和已经存活了一段时间、熬过多次GC的旧对象以获得更好的收集效果;
-
空间整合:基于标记-整理算法实现,从局部上来看是基于“复制”算法实现的,运作期间不会产生内存空间碎片,有利于程序长时间运行,分配大对象时不会因为无法找到连续内存空间而提前触发下一次GC;
-
可预测的停顿:能让使用者明确指定在一个长度为M毫秒的时间片段内,消耗在垃圾收集上的时间不得超过N毫秒;
G1收集运作过程:
-
初始标记:仅标记GC roots能直接关联到的对象;需要停顿线程,耗时
-
并发标记:是从GC Roots开始堆中对象进行可达性分析,找出存活的对象,这阶段耗时较长,但可与用户程序并发执行。
-
最终标记:是为了修正并发标记期间因用户程序继续运作而导致标记产生变动的那一部分标记记录,虚拟机将这段时间对象变化记录在线程Remembered Set Logs里面,最终标记阶段需要把Remembered Set Logs的数据合并到Remembered Set中,这阶段需要停顿线程,但是可并行执行
-
筛选回收(Live Data Counting and Evacuation):首先对各个Region的回收价值和成本进行排序,根据用户所期望的GC停顿时间来制定回收计划。这个阶段也可以做到与用户程序一起并发执行,但是因为只回收一部分Region,时间是用户可控制的,而且停顿用户线程将大幅提高收集效率。
3.CMS和G1的区别
| CMS | G1 |
JDK版本 | 1.6以上 | 1.7以上 |
回收算法 | 标记——清除 | 标记——整理 |
运行环境 | 针对70G以内的堆内存 | 可针好几百G的大内存 |
回收区域 | 老年代 | 新生代和老年代 |
内存布局 | 传统连续的新生代和老年代区域 | Region(将新生代和老年代切分成Region,默认一个Region 1 M,默认2048块) |
浮动垃圾 | 是 | 否 |
内存碎片 | 是 | 否 |
全堆扫描 | 是 | 否 |
回收时间可控 | 否 | 是 |
对象进入老年代的年龄 | 6 | 15 |
空间动态调整 | 否 | 是(新生代5%-60%动态调整,一般不需求指定) |
调优参数 | 多(近百个) | 少(十几个) |
三、2核4G和4核8GJVM参数
4核8G服务器JVM
-Xms4096M 8g内存一般分配一半的最大内存就可以了,因为机器本身还要占用一定内存
-Xmx4096M
-Xmn3072M
-Xss128k
-XX:MetaspaceSize=128m
-XX:MaxMetaspaceSize=128m
-XX:+UseParNewGC 设置年轻代为并行收集
-XX:+UseConcMarkSweepGC 使用CMS收集器
-XX:CMSInitiatingOccupancyFaction=62 当老年代的内存使用率到达62%,之后就需要进行full GC,尽量小点
-XX:+UseCMSCompactAtFullCollection 使用并行收集器,开启对老年代的压缩
-XX:CMSFullGCsBeforeCompaction=0 每次在fullGC之后就对内存碎片进行回收;可以更高效的利用老年代的内存.
四、Minor / Young /Major GC
Minor GC:在Eden区进行的;
Young GC:发生在Eden、Survivor区;
Major DC(Full GC):发生在Old区;
1.标记-清除算法
先标记出所有需要回收的对象,标记完成后同一回收所有被标记的对象
缺点:效率不高;标记清除之后会产生大量不连续的内存碎片;
2.复制算法
将可用内存划分为大小相等的两块,每次只使用其中的一块,当这一块的内存用完了,就将还存活着的着的对象复制到另一块上面,然后再把已使用过的内存空间一次清理掉。这样使得每次都是对整个半区进行内存回收,内存分配时也就不用考虑内存碎片等复杂情况,只要移动堆顶指针,按顺序分配内存即可,实现简单,运行高效。
缺点:内存代价高
3.标记-整理算法
4.分代收集算法