1、设置JVM内存
1)JVM内存分配有如下一些参数:
- -Xms:堆内存大小
- -Xmx:堆内存最大大小
- -Xmn:新生代大小,扣除新生代剩下的就是老年代大小
- -Xss:线程栈大小
- -XX:NewSize:初始新生代大小
- -XX:MaxNewSize:最大新生代大小
- -XX:InitialHeapSize:初始堆大小
- -XX:MaxHeapSize:最大堆大小
- -XX:MetaspaceSize:元空间(永久代)大小,jdk1.8 之前用 -XX:PermSize 设置
- -XX:MaxMetaspaceSize:元空间(永久代)最大大小,jdk8 之前用 -XX:MaxPermSize 设置
- -XX:SurvivorRatio:新生代 Eden 区和 Survivor 区的比例,默认为 8,即 8:1:1
一般 -Xms 和 -Xmx 设置一样的大小,-XX:MetaspaceSize 和 -XX:MaxMetaspaceSize 设置一样的大小。-Xms 等价于 -XX:InitialHeapSize,-Xmx等价于-XX:MaxHeapSize;-Xmn等价于-XX:MaxNewSize。
2)在IDEA中可以按照如下方式设置JVM参数:
3)命令行启动时可以按照如下格式设置:
java -jar -Xms1G -Xmx1G -Xmn512M -Xss1M -XX:MetaspaceSize=128M -XX:MaxMetaspaceSize=128M app.jar
2、查看GC日志
1)设置GC参数:
可以在启动时加上如下参数来查看GC日志:
- -XX:+PrintGC:打印GC日志
- -XX:+PrintGCDetails:打印详细的GC日志
- -XX:+PrintGCTimeStamps:打印每次GC发生的时间
- -Xloggc:./gc.log:设置GC日志文件的路径
例如,我在IDEA中添加了如下JVM启动参数:
-Xms1G -Xmx1G -Xmn512M -Xss1M -XX:MetaspaceSize=128M -XX:MaxMetaspaceSize=128M -XX:SurvivorRatio=8 -XX:+PrintGC -XX:+PrintGCDetails -XX:+PrintGCDateStamps -Xloggc:D:datagc.log
启动程序之后打印出了如下的一些日志:
Java HotSpot(TM) 64-Bit Server VM (25.191-b12) for windows-amd64 JRE (1.8.0_191-b12), built on Oct 6 2018 09:29:03 by "java_re" with MS VC++ 10.0 (VS2010)
Memory: 4k page, physical 8287844k(2043244k free), swap 18188876k(7512304k free)
CommandLine flags: -XX:-BytecodeVerificationLocal -XX:-BytecodeVerificationRemote -XX:CompressedClassSpaceSize=125829120 -XX:InitialHeapSize=1073741824 -XX:+ManagementServer -XX:MaxHeapSize=1073741824 -XX:MaxMetaspaceSize=134217728 -XX:MaxNewSize=536870912 -XX:MetaspaceSize=134217728 -XX:NewSize=536870912 -XX:+PrintGC -XX:+PrintGCDateStamps -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:SurvivorRatio=8 -XX:ThreadStackSize=1024 -XX:TieredStopAtLevel=1 -XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX:-UseLargePagesIndividualAllocation -XX:+UseParallelGC
2021-06-05T10:13:09.370+0800: 4.227: [GC (Allocation Failure) [PSYoungGen: 419840K->29171K(472064K)] 419840K->29275K(996352K), 0.0267009 secs] [Times: user=0.02 sys=0.00, real=0.03 secs]
2021-06-05T10:14:07.528+0800: 62.385: [GC (Allocation Failure) [PSYoungGen: 449011K->38066K(472064K)] 449115K->38218K(996352K), 0.0741401 secs] [Times: user=0.13 sys=0.06, real=0.07 secs]
从第三行 CommandLine flags 可以得到如下的信息:
- -XX:InitialHeapSize=1073741824:初始堆大小为1G(等于 -Xms 设置的值)
- -XX:MaxHeapSize=1073741824:最大堆内存 1G(等于 -Xmx 设置的值)
- -XX:NewSize=536870912:新生代初始大小 512M(等于 -Xmn 设置的值)
- -XX:MaxNewSize=536870912:最新生代初始大小 512M(等于 -Xmn 设置的值)
- -XX:MetaspaceSize=134217728:元空间大小 128M
- -XX:MaxMetaspaceSize=134217728:最大元空间 128M
- -XX:SurvivorRatio=8:新生代 Eden 和 Survivor 的比例
- -XX:ThreadStackSize=1024:线程栈的大小 1M
- -XX:+UseParallelGC:默认使用 年轻代 Parallel Scavenge + 老年代 Parallel Old 的垃圾回收器组合。
2)查看默认参数:
如果要查看JVM的默认参数,就可以通过给JVM加打印GC日志的参数,就可以在GC日志中看到JVM的默认参数了。
还可以在启动参数中添加 -XX:+PrintFlagsFinal 参数,将会打印系统的所有参数,就可以看到自己配置的参数或系统的默认参数了:
3)GC日志:
之后的日志就是每次垃圾回收时产生的日志,每行日志说明了这次GC的执行情况,例如第四行GC日志:
2021-06-05T10:24:54.618+0800: 4.318: [GC (Allocation Failure) [PSYoungGen: 419840K->28396K(472064K)] 419840K->28492K(996352K), 0.0257970 secs] [Times: user=0.11 sys=0.03, real=0.03 secs]
详细内容如下:
- 2021-06-05T10:24:54.618+0800:GC发生的时间点。
- 4.318:系统运行多久之后发生的GC,单位秒,这里就是系统运行4.318秒后发生了一次GC。
- GC (Allocation Failure):说明了触发GC的原因,这里是指对象分配失败导致的GC。
- PSYoungGen:指触发的是年轻代的垃圾回收,使用的是 Parallel Scavenge 垃圾回收器。
- 419840K->28396K:对年轻代执行了一次GC,GC之前年轻代使用了419840K,GC之后有28396K的对象活下来了。
- (472064K):年轻代可用空间是 472064K,即 461 M,为什么是461M呢?因为新生代大小为 512M,Eden 区占 409.6M,两块 Survivor 区各占 51.2M,所以年轻代的可用空间为 Eden+1个Survivor的大小,即460.8M,约为461M。
- 419840K->28492K:GC前整个堆内存使用了 419840K,GC之后堆内存使用了 28492K。
- (996352K):整个堆的大小是 996352K,即 973M,其实就是年轻代的 461M + 老年代的 512 M
- 0.0257970 secs:本次GC耗费的时间
- Times: user=0.00 sys=0.00, real=0.01 secs:本次GC耗费的时间
4)JVM退出时的GC情况:
程序结束运行后,还会打印一些日志,就是第12行之后的日志,这部分展示的是当前堆内存的使用情况:
Heap PSYoungGen total 472064K, used 243830K [0x00000000e0000000, 0x0000000100000000, 0x0000000100000000) eden space 419840K, 48% used [0x00000000e0000000,0x00000000ec88bd78,0x00000000f9a00000) from space 52224K, 73% used [0x00000000fcd00000,0x00000000ff291c40,0x0000000100000000) to space 52224K, 0% used [0x00000000f9a00000,0x00000000f9a00000,0x00000000fcd00000) ParOldGen total 524288K, used 152K [0x00000000c0000000, 0x00000000e0000000, 0x00000000e0000000) object space 524288K, 0% used [0x00000000c0000000,0x00000000c0026010,0x00000000e0000000) Metaspace used 52012K, capacity 54918K, committed 55040K, reserved 1097728K class space used 6858K, capacity 7399K, committed 7424K, reserved 1048576K
详细内容如下:
- PSYoungGen total 472064K, used 406352K:指 Parallel Scavenge 回收器负责的年轻代总共有 472064K(461M)内存,目前使用了 406352K (396.8M)。
- eden space 419840K, 93% used:Eden 区的空间为 419840K(410M),已经使用了 93%。
- from space 52224K, 27% used:From Survivor 区的空间为 52224K(51M),已经使用了 27%。
- to space 52224K, 0% used:To Survivor 区的空间为 52224K(51M),使用了 0%,就是完全空闲的。
- ParOldGen total 524288K, used 189923K:指 Parallel Old 回收器负责的老年代总共有 524288K(512M),目前使用了 189923K(185.4M)。
- object space 524288K, 36% used:老年代空间总大小 524288K(512M),使用了 36%。
- Metaspace & class space:Metaspace 元数据空间和Class空间,总容量、使用的内存等。