JVM调优必备理论知识

存活性分析(怎么找到垃圾)

根可达算法:简单地说,如果可以从任何一个已经定义的变量开始,直接或者通过其他对象的引用来访问到某个对象,则该对象是可达的

根对象:

线程变量:从一个main方法运行开始,main线程栈中调用到的其他方法,main线程栈中访问到的对象
静态变量:方法区中的类静态属性引用的对象
常量池:方法区中的常量引用的对象
JNI指针:本地方法栈中JNI(Native方法)的引用的对象

常用的垃圾回收算法

Mark-Sweep(标记清除算法)

标记阶段:通过根可达算法,将沿途的对象进行标记,标记为存活对象,其他未被标记的对象就是可回收对象。

清除阶段:将全部对象扫描一遍,没有标记的对象都进行清除。

特点:

算法相对简单,在存活对象比较多的情况下,效率比较高

扫描2遍,效率偏低

容易产生碎片

标记清除算法不适合Eden区

Copying(拷贝算法)

拷贝算法:准备一块新空间,将存活对象都复制到新空间中。然后将旧空间中的对象全部回收。

特点:

适合存活对象较少的情况,适合Eden区

相对于复制清楚算法,节省了存在大量对象时重新扫描一遍内存的开销,且不会产生碎片

但是,增加了内存消耗,实际内存使用率仅50%

HotSpot虚拟机的Serial、ParNew等新生代收集器均采用半区复制分代策略

Mark-Compact(标记压缩)

标记阶段(与标记清除算法相同):过根可达算法,将沿途的对象进行标记,标记为存活对象,其他未被标记的对象就是可回收对象。

压缩阶段:

遍历堆, 将所有对象通过计算得到新的地址并保存
遍历堆, 将所有子对象的地址更新为新的地址, 同时更新根集合中的指针.
遍历堆, 将对象集体迁移. 指针的问题都解决了, 可以将对象搬到新家了.
常用实现算法:Lisp2算法、Two-Finger算法

特点:

不会产生碎片,不会产生内存减半的问题

扫描2次,需要移动对象,效率偏低

垃圾回收器的分代

ZGC之前的算法存在分代,ZGC及以后的算法不在进行分代

垃圾回收器分代,分为逻辑分代和物理分代

其中,G1仅在逻辑分代,物理不分代

物理分代:

区分为:Young(新生代) Old(老年代) 其中新生代:老年代=1:3

新生代又可以细分为:Eden区,Survivor区(分为survivor0,survivor1,也是常说的from,to)

按垃圾回收发生的范围:

新生代收集Minor GC/Young GC:指目标只是新生代的垃圾收集。
老年代收集Major GC/Old GC:指目标只是老年代的垃圾收集。
整堆收集(Full GC):收集整个Java堆和方法区的垃圾收集。
新创建的对象都会被分配到Eden区(一些大对象特殊处理),这些对象经过第一次Minor GC后,如果仍然存活,将会被移到Survivor区。对象在Survivor区中每熬过一次Minor GC,年龄就会增加1岁,当它的年龄增加到一定程度时,就会被移动到年老代中

当Survivor空间不足以容纳一次Minor GC之后存活的对象时,就需要依赖其他内存区域(实
际上大多就是老年代)进行分配担保(Handle Promotion)

新生代 + 老年代 + 永久代(1.7)Perm Generation/ 元数据区(1.8) Metaspace

  1. 永久代 元数据 - Class
  2. 永久代必须指定大小限制 ,元数据可以设置,也可以不设置,无上限(受限于物理内存)
  3. 字符串常量 1.7 - 永久代,1.8 - 堆
  4. MethodArea逻辑概念 - 永久代、元数据

常用的垃圾回收器

Serial 年轻代 串行回收
PS 年轻代 并行回收(jdk1.8默认)
ParNew 年轻代 配合CMS的并行回收
SerialOld
ParallelOld
Serial:当工作时所有工作线程都停止,当工作的时候断开的线程则是垃圾,如果突然加入Serial,则停止,进行垃圾清理

safe point: 线程停止

Serial Old:用在老年代,使用标记压缩的算法,用的也是单线程

Parallel Scavenge:jdk1.8默认垃圾回收器

Parallel Old:标记压缩算法

ParNew: Parallel New,在Parallel Scavenge的基础上做了一些增强,以便可以配合CMS使用

CMS:

初始标记:标记根节点
并发标记:工作线程和标记同事进行(CMS耗时最长的阶段)
重新标记:并发标记过程中重新产生的垃圾,重新标记一次
并发清理:并发清理阶段会产生浮动垃圾
ConcurrentMarkSweep 老年代 并发的, 垃圾回收和应用程序同时运行,降低STW的时间(200ms)
CMS问题比较多,所以现在没有一个版本默认是CMS,只能手工指定
CMS既然是MarkSweep,

就一定会有碎片化的问题,碎片到达一定程度,
CMS的老年代分配对象分配不下的时候,使用SerialOld 进行老年代回收
并发标记的算法
CMS使用:三色标记算法+incremental Update算法

G1:三色标记算法+SATB算法,主要配合他的Rset来进行

ZGC:用的是颜色指针

猜你喜欢

转载自blog.csdn.net/liuerchong/article/details/123712282
今日推荐