共计 6480 个字符,预计需要花费 17 分钟才能阅读完成。
这篇文章主要讲解了“JVM 的参数有哪些”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着丸趣 TV 小编的思路慢慢深入,一起来研究和学习“JVM 的参数有哪些”吧!
垃圾收集策略:
垃圾收集的 3 种模式:
Serial GC
串行收集:适合内存有限的情况,回收慢。
Parallel GC
并行收集:效率高,当 Heap 较大时,系统暂停时间较长。
CMS GC
并发收集:Old 区回收暂停时间短,整个 GC 耗时较长、比较耗 CPU 资源。
参数:
Serial GC:
-XX:+UseSerialGC 使用串行收集模式,即使用 Serail + Serail Old 进行回收。虚拟机运行在 client 模式下的默认选项。
Parallel GC:
-XX:+UseParallelGC 使用 Parallel Scavenge + Serail Old 进行回收。虚拟机运行在 server 模式下的默认选项。
-XX:+UseParNewGC 使用 ParNew + Serial Old 来进行回收。设置新生代的收集器为 ParNew 收集器(并行收集器)。该设置默认是关闭的,打开该开关后,jvm 会使用 ParNew + Serial Old 来进行 gc。
-XX:ParallelGCThreads ParNew 收集器的收集线程数,默认与 CPU 的数量相同。
-XX:+UseParallelOldGC 使用 Parallel Scavenge + Parallel Old 进行回收。
CMS GC:
-XX:+UseConcMarkSweepGC 使用 ParNew + CMS 收集器 (并发收集失败(Concurrent Mode Failure) 后使用 Serial Old 收集器)
-XX:+CMSParallelRemarkEnabled 开启并行 remark,以减少 remark 时程序暂停的时间。
-XX:CMSInitiatingOccupancyFraction=70 当老年代的空间被占用 70%后,CMS 收集器开始 gc。
1 JVM 会收集对象分配和释放的运行时数据,并且通过分析这些数据来决定什么时候应该进行一次 gc(即: 启动一次 CMS 垃圾收集器)。
2 为了引导这一过程,JVM 会在启动 CMS 收集器前进行一些线索查找,该线索由 -XX:CMSInitiatingOccupancyFraction 来设置,该值表示老年代的使用率。
-XX:+UseCMSInitiatingOccupancyOnly 命令 JVM 不要根据运行时收集的数据来判断什么时候开始 gc,而是根据 CMSInitiatingOccupancyFraction 的值来判断是否进行 CMS 收集。注意:一般不会打开该开关。
-XX:+UseCMSCompactAtFullCollection CMS 收集器在 gc 时,允许对老年代进行压缩,解决因标记 - 清除算法导致的内存碎片的问题。
-XX:CMSFullGCsBeforeCompaction=0 CMS 收集器 gc 多少次后进行内存压缩(整理),由于 CMS 收集器使用的是标记 - 清除算法,所以 CMS 在 gc 后会产生内存碎片,使得运行效率降低。
-XX:+CMSClassUnloadingEnabled 开启 CMS 收集器对永久代的 gc(默认不会对永久代进行 gc)。
-XX:CMSInitiatingPermOccupancyFraction 设置永久代使用到达多少比率时触发 CMS 收集器的 gc
-XX:+DisableExplicitGC 禁止 System.gc(),避免因开发人员不恰当地调用 System.gc()方法对系统性能造成的不良的影响。
-Xnoclassgc 禁用类垃圾回收功能,也就避免了同一个类的加载、卸载、(再次用到该类时)再加载的操作,性能会高一点。
1 虚拟机加载类的过程中包含了 IO 和内存分配等操作,故 JVM 在加载类时会对性能产生一定的影响。
-XX:+UseFastAccessorMethods 优化原始类型的 getter 方法的性能,默认开启。
-XX:+PrintClassHistogram 遇到 Ctrl+Break 中断,打印类实例的柱状信息,与 jmap -histo 功能相同
-XX:SoftRefLRUPolicyMSPerMB=0 设置每兆堆空闲空间中软引用(SoftReference) 的存活时间,默认值为 1(秒)。
1 softly reachable objects will remain alive for some amount of time after the last time they were referenced. The default value is one second of lifetime per free megabyte in the heap.
2 SoftReference 是在 gc 时才被回收,故 SoftReference 实际的存活时间可能比这个设定的值要大。
3 一般情况下,建议设置为 0。
辅助信息:
-XX:+PrintGCDetails 打印 GC 的详细信息
-XX:+PrintGCTimeStamps 打印 GC 的时间戳
-XX:+PrintHeapAtGC 打印 GC 前后堆栈的详细信息
-Xloggc: 设置 gc 的 log 日志。eg:-Xloggc:$CATALINA_BASE/logs/gc.log
堆栈:
【堆】
-Xms 或 -XX:InitialHeapSize 初始堆大小,默认空余堆内存小于 40%(MinHeapFreeRatio 参数可以调整)时,JVM 就会增大堆直到 -Xmx 的最大限制。
-Xmx 或 -XX:MaxHeapSize 最大堆大小,默认空余堆内存大于 70%(MaxHeapFreeRatio 参数可以调整)时,JVM 会减少堆直到 -Xms 的最小限制。
-Xmn 新生代大小:
1 新生代越大也就意味着会有更多的对象在 minor GC 期间被回收,如果设置的太大,则老年代就变小了,可能会频繁触发 Full GC,甚至是 OOM。
2 如果新生代设置的太小,则会导致 minor GC 更加频繁,进而会导致更多的对象直接进入老年代,当老年代已使用的空间到达一定比例时,会触发 Full GC。
-XX:NewSize 设置新生代大小
-XX:NewRatio 新生代(Eden+ 2 个 Survivor) 最大容量与老年代最大容量的比值,默认为 2,即:NewSize : OldSize = 1:2 注意:该参数的值 = 老年代最大容量大小 / 新生代最大容量大小。
eg:jstat -gccapacity PID # 查看 NGCMX、OGCMN 即可验证。
-XX:SurvivorRatio 设置 Eden 与 1 个 Survivor 的比值,默认为 8,即 Eden : Survivor1 : Survivor2 = 8:1:1
1 Eden 越大也就意味着发生 minor GC 的频率越低,如果 Eden 设置的太大,造成 Survivor 太小,则会导致要回收的对象在 minor GC 后就直接进入老年代,从而更频繁地触发 Full GC。
【栈】
-Xss 每个线程的栈大小:
1 在相同物理内存下:减小这个值能生成更多的线程,但是操作系统对一个进程内的线程数是有限制的,不能无限生成 (网上说是 3k-5k 左右,没有做过测试)。
2 一般比较小的系统,如果栈不是很深,则 128k 就够用了,较大的系统则应设置为 256k。
3 jdk5 之后,每个线程堆栈大小默认为 1M。
【永久代】
-XX:PermSize 设置永久代初始值
-XX:MaxPermSize 设置持久代最大值
【其它】
-XX:+TraceClassLoading 跟踪类加载和卸载的信息,一般我们在排查内存泄露、jar 包版本冲突等问题时会添加这个参数。
-XX:-OmitStackTraceInFastThrow
说明:
jdk1.5 后,为了提高性能,JVM 在以 Server 模式运行时,当一些异常在代码里某个特定位置被抛出很多次后,编译器(C2) 会对该方法进行重编译,重编译后,若再次出现该异常,则会抛出一个提前准备好的没有调用栈的异常。通过 -XX:-OmitStackTraceInFastThrow 可以禁用该默认的优化。
官方:
The compiler in the server VM now provides correct stack backtraces for all cold built-in exceptions.
For performance purposes, when such an exception is thrown a few times, the method may be recompiled.
After recompilation, the compiler may choose a faster tactic using preallocated exceptions that do not provide a stack trace.
-XX:LargePageSizeInBytes=128 设置内存页的大小
-XX:MaxTenuringThreshold GC 最大年龄
1 如果设置为 0,则新生代对象不经过 Survivor 区,直接进入老年代。对于老年代中对象比较多的应用,可以提高效率。 2 如果设置为一个较大的值,则新生代对象会在 Survivor 区进行多次复制,这样可以增加对象在新生代的存活时间,增加对象在新生代被回收的概率,该参数只有在串行 GC 时才有效。
域名解析:
-Dsun.net.spi.nameservice.provider.1=dns,sun 指定域名解析器 https://docs.oracle.com/javase/8/docs/technotes/guides/net/properties.html
举例:无法解析某个域名,报 java.net.UnknownHostException 错误
解决:启动的时候添加参数 -Dsun.net.spi.nameservice.provider.1=dns,sun
补充:
-XX:CMSInitiatingOccupancyFraction 与 -Xmn 之间的关系:
内存分配担保失败 (promontion faild) 的原因:
1)Minor GC 时,将 eden 和 survivor from 中存活的对象复制到 survivor to 中的时候,如果 survivor to 容纳不下这些对象,那么这些对象将晋升到老年代,
2)此时,如果老年代中剩余的空间也无法容纳下这些对象,那么就会导致内存分配担保失败(promontion faild),进而引发了 full gc。
结论:当新生代与老年代满足 eden + survivor from = 老年代剩余的空间 关系时,promontion faild 就不会发生。
即:eden + survivor from = (Xmx-Xmn)*(1-CMSInitiatingOccupancyFraction/100)
由方程组:
Eden / Survivor=SurvivorRatio
Eden + 2Survivor=Xmn
Survivor * SurvivorRatio + 2Survivor = Xmn === Survivor = Xmn/(SurvivorRatio+2)
可得出:
Eden + Survivor = Xmn-Survivor = Xmn – Xmn/(SurvivorRatio+2)
即:Xmn – Xmn/(SurvivorRatio+2) = (Xmx-Xmn)*(1-CMSInitiatingOccupancyFraction/100)
简化:
CMSInitiatingOccupancyFraction = (1 – (Xmn-Xmn/(SurvivorRatio+2))/(Xmx-Xmn)) * 100
eg:如果 -Xms8G -Xmx8G -Xmn3G -XX:SurvivorRatio=8,则 CMSInitiatingOccupancyFraction = (1 – (3-3/(8+2))/(8-3))) = 46%
CMSInitiatingOccupancyFraction 低于 70% 需要调整 xmn 或 SurvivorRatior 值。
===================================================================================
网上某大牛的配置,据称可以支持每天几百万的 pv。
JAVA_OPTS=
-Dresin.home=$SERVER_ROOT
-server
-Xms6000M
-Xmx6000M
-Xmn500M
-XX:PermSize=500M
-XX:MaxPermSize=500M
-XX:SurvivorRatio=65536
-XX:MaxTenuringThreshold=0
-Xnoclassgc
-XX:+DisableExplicitGC
-XX:+UseParNewGC
-XX:+UseConcMarkSweepGC
-XX:+UseCMSCompactAtFullCollection
-XX:CMSFullGCsBeforeCompaction=0
-XX:+CMSClassUnloadingEnabled
-XX:+CMSParallelRemarkEnabled
-XX:CMSInitiatingOccupancyFraction=90
-XX:SoftRefLRUPolicyMSPerMB=0
-XX:+PrintClassHistogram
-XX:+PrintGCDetails
-XX:+PrintGCTimeStamps
-XX:+PrintHeapAtGC
-Xloggc:log/gc.log
说明:
1)-XX:SurvivorRatio=65536 -XX:MaxTenuringThreshold=0 表示在新生代中去掉了 Survivor,即新生代中只有 Eden
===================================================================================
感谢各位的阅读,以上就是“JVM 的参数有哪些”的内容了,经过本文的学习后,相信大家对 JVM 的参数有哪些这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是丸趣 TV,丸趣 TV 小编将为大家推送更多相关知识点的文章,欢迎关注!