在学习java的jvm内存板块时,最后总会涉及到一些JVM参数。年轻代、老年代、永久代等各项都可以通过JVM参数来设置大小。在实际设置启动参数时,一般只会设置几个,实际参数有上百个,很多都有默认值。

JVM中,上一个版本的默认值并不一定是下一版本的默认值,不同的GC方式有不同的整套默认值,os不同,jvm位数不同,默认值都会有所区别。jdk1.6 高版本的update中参数得有600个。参数过多,不需要全部了解,只要知道的是找到默认值的方法,掌握默认值的大概量级、在不同的版本下哪些是常用的默认参数,哪些是必须设置的参数,哪些是可以选择的,哪些是尽量不要碰的。


看默认值的方法?

1、通过jinfo来获取。比如,jinfo -flag -PrintHeapAtGC=true <pid>

2、通过java -XX:+PrintFlagsFinal -version来获取结果。

3、通过java -XX:+PrintCommandLineFlags来打印真正的参数启动命令。

4、如果这些参数还不够全,可以打开几个开关:

​java -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+PrintFlagsFinal -version​

大部分的参数都可以安全的看到默认值,但是某些参数需要在生产环境运行时来调整。(后面花括号里面有product的表示可以在启动参数中设置的,花括号里面是“product rw”的表示还可以在jvm启动后使用类似下面的命令来设置这些参数)


项多时,可以根据grep命令指定单一项参数。



$ java -XX:+PrintCommandLineFlags -version
-XX:InitialHeapSize=128163136 -XX:MaxHeapSize=2050610176 -XX:+PrintCommandLineFlags -XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX:+UseParallelGC
java version "1.8.0_144"
Java(TM) SE Runtime Environment (build 1.8.0_144-b01)
Java HotSpot(TM) 64-Bit Server VM (build 25.144-b01, mixed mode)




JVM参数设置中,有的是同一类型有很多参数,而且都有默认值。如-XX:NewSize、-XX:MaxNewSize,设置了xmn后相当于将这两值值设置为一样大。也有用参数-XX:NewRatio来设置的。不要混用,否则实际就并不知如何执行的。


参数 -XX:+PrintTenuringDistribution 输出中的部分值可以通过其它参数控制。

通过 -XX:InitialTenuringThreshold 和 -XX:MaxTenuringThreshold 可以设定老年代阀值的初始值和最大值。

通过参数 -XX:TargetSurvivorRatio 设定幸存区的目标使用率.例如 , -XX:MaxTenuringThreshold=10 -XX:TargetSurvivorRatio=90 设定老年代阀值的上限为10,幸存区空间目标使用率为90%。


新生代的GC 使用复制算法。

进入老年代的可能:1)复制对象超过gc次数;2)复制对象大于from/to区大小;3)创建对象大于新生代剩余空间大小;

如果新生代过小,会导致新生对象很快就晋升到老年代中,在老年代中对象很难被回收。

有多种方式,设置新生代行为,没有通用准则。我们必须清楚以下2中情况:

1 如果从年龄分布中发现,有很多对象的年龄持续增长,在到达老年代阀值之前。这表示 -XX:MaxTenuringThreshold 设置过大

2 如果 -XX:MaxTenuringThreshold 的值大于1,但是很多对象年龄从未大于1.应该看下幸存区的目标使用率。如果幸存区使用率从未到达,这表示对象都被GC回收,这正是我们想要的。 如果幸存区使用率经常达到,有些年龄超过1的对象被移动到老年代中。这种情况,可以尝试调整幸存区大小或目标使用率。


jvm参数设置输出结果

1、gc日志输出

在 jvm启动参数中加入 -XX:+PrintGC -XX:+PrintGCDetails -XX:+PrintGCTimestamps -XX:+PrintGCApplicationStopedTime ,

其他还有 -Xloggc:文件路径, -verbose:gc -XX:+PrintTenuringDistribution


-XX:+PrintGCApplicationStoppedTime -XX:+PrintGCApplicationConcurrentTime

打开这些选项能够记录下所有的安全点(应用程序线程可以被安全地停止掉的那个时间点),而不止是GC暂停的。



Application time: 0.3440086 seconds
Total time for which application threads were stopped: 0.0620105 seconds
Application time: 0.2100691 seconds
Total time for which application threads were stopped: 0.0890223 seconds


从中可以得知应用程序在前344毫秒中是在处理实际工作的,然后将所有线程暂停了62毫秒,紧接着又工作了210ms,然后又暂停了89ms。

-XX:+PrintGCDetails -XX:+PrintGCApplicationStoppedTime -XX:+PrintGCApplicationConcurrentTime输出则变成这样了;





[Full GC (Ergonomics) [PSYoungGen: 1375253K->0K(1387008K)] [ParOldGen: 2796146K->2049K(1784832K)] 4171400K->2049K(3171840K), [Metaspace: 3134K->3134K(1056768K)], 0.0571841 secs] [Times: user=0.02 sys=0.04, real=0.06 secs]
Total time for which application threads were stopped: 0.0572646 seconds, Stopping threads took: 0.0000088 seconds


综上可知,应用线程被强制暂停了57ms来进行垃圾回收。其中又有0.008ms是用来等待所有的应用线程都到达安全点。

详细了解安全点信息:-XX:+PrintSafepointStatistics -XX:PrintSafepointStatisticsCount=1 会使得JVM会将一些额外的信息记录到标准输出中


参数 -XX:+PrintTenuringDistribution 指定JVM 在每次新生代GC时,输出幸存区中对象的年龄分布。



2、jvm outOfMemory时dump内存

-XX:+HeapDumpOnOutOfMemoryError


3、jvm FGC前后dump内存

XX:+HeapDumpBeforeFullGC -XX:+HeapDumpAfterFullGC


4 crash日志





[GC [DefNew: 1986K->128K(2112K),0.0011191 secs] 27809K->27808K(30528K), 0.0011425 secs] [Times: user=0.00sys=0.01, real=0.00 secs]

[GC [ParNew: 1990K->132K(2112K),0.0007742 secs] 24112K->24110K(30528K), 0.0007964 secs] [Times: user=0.00sys=0.00, real=0.00 secs]

[GC [PSYoungGen:7449K->3728K(7552K)] 66980K->66980K(75136K), 0.0022792 secs] [Times:user=0.00 sys=0.00, real=0.00 secs]

GC[ParNew 表示使用的是parNew收集器。

GC[DefNew 表示用的是serial收集器。

[GC[PSYoungGen 表示用的是Parallel Scavenge收集器。