本文将分门别类地介绍一些常用的JVM的参数,包括:
-Xmx
指定堆内存的最大空间,设置方式:-Xmx<value>
-Xms
指定堆内存的初始空间,设置方式:-Xms<value>
oracle官方推荐将初始堆Xms与最大堆Xmx设置为相等。这样的好处是,可以减少程序运行时进行垃圾回收的次数,同时也减少了虚拟机需要做出决策的数量,这些可以提高程序的性能。
我的经验是,如果java进程的可用内存在4G以内(含),我会配置堆空间占50%的内存。如果java进程的可用内存大于4G,那么我会配置堆空间60%的内存。举例:如果一个docker容器的内存limit是4G,那么我会配置 -Xmx2048m -Xms2048m
。
堆的大小设置完了以后,来分配堆里面的新生代内存。
-XX:NewRatio
指定老年代与新生代的比例。-XX:MaxNewSize=size
指定新生代的最大空间。-XX:NewSize=size
指定新生代的初始空间。堆空间由新生代和老年代组成,老年代是兜底的区域,如果空间太小的话,要么频繁Full GC,要么进程OOM。-XX:NewRatio
的默认值是2,意味着老年代是新生代的两倍,新生代为堆空间的1/3。如果你想更保守的话,可以设置为3,意味着新生代只占堆空间的1/4,老年代更大,缺点是可能会带来更频繁的新生代GC。
-XX:SurvivorRatio
指定新生代中的eden区与s0和s1的比例。默认值是8,意味着eden区默认是s0和s1的8倍。在JDK1.6和JDK1.7等版本中,可以使用-XX:PermSize和XX:MaxPermSize
配置永久区大小。其中,-XX:PermSize
表示初始的永久区大小,-XX:MaxPermSize
表示最大永久区大小。
从JDK1.8开始,永久区被彻底移除,使用了新的元数据区存放类的元数据。在默认情况下,元数据区只受系统可用内存的限制,但依然可以使用参数-XX:MetaspaceSize
和-XX:MaxMetaspaceSize
指定永久区的初始值和最大值。-XX:MetaspaceSize
的默认值是20M,而-XX:MaxMetaspaceSize
没有最大值。推荐的配置为:
-XX:MetaspaceSize=96m -XX:MaxMetaspaceSize=256m。
使用-Xss
指定线程栈的大小,默认是1M。可以通过Xss256k
来指定每个线程栈的大小为256k。
直接内存也是Java程序中非常重要的组成部分,特别是在NIO被广泛使用后,直接内存的使用也变得非常普遍。直接内存跳过了Java堆,使Java程序可以直接访问原生堆空间。因此,从一定程度上加快了内存空间的访问速度。但是,武断地认为使用直接内存一定可以提高内存访问速度也是不正确的。最大可用直接内存可以使用参数-XX:MaxDirectMemorySize
设置,如果不设置,默认值为最大堆空间,即-Xmx
的值。当直接内存使用量达到-XX:MaxDirectMemorySize
时,就会触发垃圾回收,如果垃圾回收不能有效释放足够的空间,直接内存溢出依然会引起系统的OOM。
可以通过配置参数-XX:+HeapDumpOnOutOfMemoryError
,当java堆出现内存溢出时会导出整个堆的信息。配合-XX:HeapDumpPath=<path>
,可以指定导出堆的存放路径。
除此以外,在OOM发生时还可以通过-XX:OnOutOfMemoryError=<my-script>
来执行一个脚本。其中,<my-script>
可以是一个脚本文件,也可以是多条命令,其中的%p
将会被替换为pid。例如:
-XX:OnOutOfMemoryError="jstack -F %p > jstack.txt "
-XX:+PrintGC(在JDK9、JDK10中建议使用`-Xlog:gc`)
-XX:+PrintGCDateStamps
如果同时配置以上的两个参数,则会产生类似的GC日志
2021-10-07T15:27:57.471+0800: [GC pause (G1 Evacuation Pause) (young) 657M->74M(2048M), 0.0229247 secs]
2021-10-07T23:49:54.850+0800: [GC pause (G1 Evacuation Pause) (young) 657M->72M(2048M), 0.0279736 secs]
2021-10-08T08:11:09.035+0800: [GC pause (G1 Evacuation Pause) (young) 657M->72M(2048M), 0.0278149 secs]
我们可以看出GC发生的时间,GC的类型(young GC),堆的占用空间从657M降到了70多M,堆的空间上限为2048M,GC的过程用时0.02秒等信息。
如果需要更加详细的信息,可以使用-XX:+PrintGCDetails
参数。(JDK9、JDK10建议使用-Xlog:gc/*
)。
它会在日志中分别输出堆的各区域的内存回收情况。
默认情况下,GC的日志会在控制台中输出,这不便于后续分析和定位问题。所以,虚拟机允许将GC日志以文件的形式输出,可以使用参数-Xloggc:<logfile>
指定。(在JDK9、JDK10中建议使用-Xlog:gc:<logfile>
)
从JDK9开始,G1收集器被设为了默认的垃圾收集器,所以我在这里只列跟G1相关的参数
-XX:+UseG1GC
:使用G1回收器;-XX:MaxGCPauseMillis=xxx
:设置最大垃圾回收停顿时间,默认值是200。
可以使用参数-verbose:class
跟踪类的加载/卸载。
也可以单独使用参数-XX:+TraceClassLoading
跟踪类的加载,使用参数-XX:+TraceClassUnloading
跟踪类的卸载。这两类参数是等价的。
通过-XX:+PrintCommandLineFlags
参数,可以在java进程启动时打印当前进程实际应用的所有参数。
通过-XX:+PrintVMOptions
参数,可以在java进程启动时打印我们显式地为当前java进程设置了哪些参数。
当然,也可以直接运行jps -v
命令来查看java进程显式设置的参数。
以下命令可以显示当前机器上的jdk版本的所有参数的默认值
java -XX:+PrintFlagsFinal -version
配合grep
就可以查看你想查看的参数的默认值了。比如查看NewRatio
的默认值到底是几比几:
$ java -XX:+PrintFlagsFinal -version |grep NewRatio
uintx NewRatio = 2 {product}
java version "1.8.0_291"
Java(TM) SE Runtime Environment (build 1.8.0_291-b10)
Java HotSpot(TM) 64-Bit Server VM (build 25.291-b10, mixed mode)
版权说明 : 本文为转载文章, 版权归原作者所有 版权申明
原文链接 : https://blog.csdn.net/daguanjia11/article/details/120655483
内容来源于网络,如有侵权,请联系作者删除!