JDK8 https://docs.oracle.com/javase/8/docs/technotes/guides/vm/gctuning/
JDK11 https://docs.oracle.com/en/java/javase/11/gctuning/index.html
JVM内存管理 https://www.oracle.com/technetwork/java/javase/tech/memorymanagement-whitepaper-1-150020.pdf
JVM Heap分为年轻代
, 年老代
区域名称 | 所属 | 作用 |
---|---|---|
eden | 年轻代 | 取名来自伊甸园 , 大多数java对象都是从eden 区分配内存 |
survivor | 年轻代 | 由s1 , s2 两个区组成, 其中一个保持是空的, 当另外一个区满了之后, 会将对象转移到空的区域中, 如果对象如此倒腾多次之后, 仍然存活, 则将这个对象转移到 年老代 |
old | 年老代 | 年轻代中存活下来的对象最终会转移到年老代中, 有些较大的对象, 也可能直接分配在年老代 |
年轻代内存满了之后, 会执行minor gc
也叫major gc
年老代内存满了之后, 会执行full gc
gc时, 会导致jvm暂停运行. 因此gc调优的重要指标:
https://docs.oracle.com/en/java/javase/11/gctuning/concurrent-mark-sweep-cms-collector.html#GUID-FF8150AC-73D9-4780-91DD-148E63FA1BFF
服务器端通常使用这个回收器. 因为服务端通常会分配很大我内存, 比如2个G. 靠串行之类的回收, 肯定不行.
流程:
缺点:
会产生内存碎片.
其它的回收器没用过, 不说了, 看文档吧
实现目标:
这个就靠经验了.
https://docs.oracle.com/javase/8/docs/technotes/tools/unix/jstat.html
比如, 观察年轻代的GC情况
jstat -gcnew 14344 2000
S0C S1C S0U S1U TT MTT DSS EC EU YGC YGCT
102400.0 102400.0 54963.8 0.0 15 15 51200.0 204800.0 199720.3 175474 7723.720
102400.0 102400.0 0.0 72970.3 1 15 51200.0 204800.0 28428.1 175475 7723.760
YGC
为young gc的次数
YGCT
为young gc所花费的总时间,
本例中, 本次gc花费了40毫秒
同样, 可以打印old gc的状况
jstat -gcold 14344 2000
https://docs.oracle.com/javase/8/docs/technotes/guides/vm/gctuning/cms.html
https://docs.oracle.com/en/java/javase/11/gctuning/concurrent-mark-sweep-cms-collector.html#GUID-704EEEB0-EE76-44D4-BA18-FA92F5A7574A
下例中 (需要启用GC日志)
major gc时, JVM暂停的时间包括:
Initial Mark
0.0051491 secs
CMS-remark
0.2138783 secs
minor gc的时间为0.0463569 (Allocation Failure开始那行)
2019-02-12T14:42:57.342+0800: 6099136.165: [GC (CMS Initial Mark) [1 CMS-initial-mark: 502696K(546176K)] 515234K(750976K), 0.0051491 secs] [Times: user=0.01 sys=0.00, real=0.00 secs]
2019-02-12T14:42:57.348+0800: 6099136.170: [CMS-concurrent-mark-start]
2019-02-12T14:42:57.630+0800: 6099136.453: [CMS-concurrent-mark: 0.283/0.283 secs] [Times: user=0.19 sys=0.11, real=0.28 secs]
2019-02-12T14:42:57.630+0800: 6099136.453: [CMS-concurrent-preclean-start]
2019-02-12T14:42:57.651+0800: 6099136.473: [CMS-concurrent-preclean: 0.020/0.020 secs] [Times: user=0.01 sys=0.01, real=0.02 secs]
2019-02-12T14:42:57.651+0800: 6099136.473: [CMS-concurrent-abortable-preclean-start]
CMS: abort preclean due to time
2019-02-12T14:43:02.760+0800: 6099141.582: [CMS-concurrent-abortable-preclean: 1.999/5.109 secs] [Times: user=7.12 sys=0.00, real=5.11 secs]
2019-02-12T14:43:02.760+0800: 6099141.583: [GC (CMS Final Remark) [YG occupancy: 53344 K (204800 K)]
2019-02-12T14:43:02.760+0800: 6099141.583: [Rescan (parallel) , 0.0137956 secs]
2019-02-12T14:43:02.774+0800: 6099141.597: [weak refs processing, 0.1713338 secs]
2019-02-12T14:43:02.946+0800: 6099141.768: [class unloading, 0.0086490 secs]
2019-02-12T14:43:02.954+0800: 6099141.777: [scrub symbol table, 0.0026173 secs]
2019-02-12T14:43:02.957+0800: 6099141.779: [scrub string table, 0.0006322 secs][1 CMS-remark: 502696K(546176K)] 556040K(750976K), 0.2138783 secs] [Times: user=0.00 sys=0.00, real=0.22 secs]
2019-02-12T14:43:02.977+0800: 6099141.799: [CMS-concurrent-sweep-start]
2019-02-12T14:43:03.193+0800: 6099142.016: [CMS-concurrent-sweep: 0.216/0.216 secs] [Times: user=0.00 sys=0.00, real=0.21 secs]
2019-02-12T14:43:03.193+0800: 6099142.016: [CMS-concurrent-reset-start]
2019-02-12T14:43:03.195+0800: 6099142.017: [CMS-concurrent-reset: 0.001/0.001 secs] [Times: user=0.00 sys=0.00, real=0.01 secs]
2019-02-12T14:43:03.805+0800: 6099142.628: [GC (Allocation Failure)
2019-02-12T14:43:03.806+0800: 6099142.628: [ParNew: 146395K->7398K(204800K), 0.0462122 secs] 439184K->300273K(750976K), 0.0463569 secs] [Times: user=0.00 sys=0.00, real=0.04 secs]
Heap上限与初始值
-Xms1g -Xmx1g
, 设置成相等. (对于服务端来说, 就是要一直稳定运行)
年轻代大小
-XX:NewRatio=2
, 年轻代与年老代的比值为1:2
-XX:NewSize=100m
, 年轻代大小设置成指定的值
-XX:SurvivorRatio=2
, eden区与单个Survivor区的比率大小
-XX:MaxGCPauseMillis=250
设置GC暂停允许的最大时间
-XX:ParallelGCThreads=4
并行GC的线程数
-XX:+UseConcMarkSweepGC
指定使用CMS回收器
开启GC日志
-XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=3 -XX:+PrintGCDetails -XX:+PrintGCDateStamps \
-XX:PrintFLSStatistics=2 -XX:+PrintGCApplicationStoppedTime -XX:+PrintHeapAtGC \
-XX:GCLogFileSize=2048K -XX:+PrintFlagsFinal