理解JVM GC对于咱们把控Java应用有很大的帮助。下面我从运维角度,把网上的JVM相关的资料整理以下,以加深对JVM GC的理解。
若有错误的地方,请看官指正。算法
JVM内存使用分类多线程
JVM的内存分区关系:运维
关于年轻代、年老代、持久代jvm
对于JVM来讲,内存分为三个区域:年轻代、年老代和持久代。年轻代和年老代用来存放Java进程中的变量,持久代用于放Java类信息。
通常对咱们主要关注年轻代和年老代。JVM的分代能够用下面这张图表示:oop
年轻代分为三个区域:一个Eden区(简称E区域),两个Survivor区(咱们定义为S0、S1)。
Java程序新申请的变量会放在E区;当E区满时,全部存活的对象会被移动到S0区。当S0区满时,S0中存活的对象被移动到S1区(这时候S0就空了,E区满时存活的对象会移动到S1区)。当S1区满时,将经历过S0的对象移动到年老代(O区)。S0区和S1区是对等的,这样一个对象要进入持久代会经历E区、S0区、S1区,而后进入到O区。spa
年老代用于存放从年轻代晋升上来的对象(E区->S0区->S1区->O区),通常咱们设置的时候年老大比较大。线程
使用jstat查看当前Java进程JVM各区的状况对象
使用方法blog
jstat -gcutil 进程pid 刷新秒s
举例进程
[hadoop@localhost ~]$ jstat -gcutil 6572 1s S0 S1 E O P YGC YGCT FGC FGCT GCT 0.00 0.13 10.61 60.38 63.44 249 117.204 2 1.468 118.673 0.00 0.13 10.61 60.38 63.44 249 117.204 2 1.468 118.673 0.00 0.13 10.61 60.38 63.44 249 117.204 2 1.468 118.673 0.00 0.13 10.61 60.38 63.44 249 117.204 2 1.468 118.673 0.00 0.13 10.61 60.38 63.44 249 117.204 2 1.468 118.673 0.00 0.13 10.61 60.38 63.44 249 117.204 2 1.468 118.673 0.00 0.13 10.61 60.38 63.44 249 117.204 2 1.468 118.673 0.00 0.13 10.61 60.38 63.44 249 117.204 2 1.468 118.673 0.00 0.13 10.61 60.38 63.44 249 117.204 2 1.468 118.673 0.00 0.13 10.61 60.38 63.44 249 117.204 2 1.468 118.673
这里能够看到S0、S一、E、O区各个使用率状况,另外还有gc的次数统计
另外:
young GC:当young gen中的eden区分配满的时候触发
full GC:当准备要触发一次young GC时,若是发现统计数听说以前young GC的平均晋升大小比目前old gen剩余的空间大,则不会触发young GC而是转为触发full GC
年轻代和年老代的 GC 关系
因为JVM的内存有限,而Java应用程序不会管理不用的内存,因此JVM须要一种垃圾回收机制(Garbage Collection),这就是JVM GC机制。
目前常见的GC收集器的概况以下:
内存区 | GC算法 | 是否多线程 | 是否stop-the-world |
年轻代 | Serial | 单线程 | 是 |
年轻代 | ParNew | 多线程 | 是 |
年轻代 | Parallel Scavenge | 多线程 | 是 |
年老代 | CMS | 多线程 | 整个过程有2次短暂stop-the-world |
年老代 | Serial Old(MSC) | 单线程 | 是 |
年老代 | Parallel Old | 多线程 | unkown |
年轻代和年老代都有各自的垃圾回收机制。而且在咱们实际使用的时候,是相互搭配的,具体搭配关系见下图: