JVM - 图1

内存溢出和内存泄漏

渣男的三个例子
由直接内存导致的内存溢出, 一个明显的特征是在Heap Dump文件中不会看见有什么明显的异常情况, 如果读者发现内存溢出之后产生的Dump文件很小, 而程序中又直接或间接使用了DirectMemory(典型的间接使用就是NIO) , 那就可以考虑重点检查一下直接内存方面的原因了。

垃圾收集器

Serial收集器

是Hotspot在client模式下的默认垃圾回收器。新生代采用的是SerialNew,复制算法,老年代采用的是SerialOld,标记整理算法。都是单线程工作模式。优点是实现简单,单线程模式下较高效。

ParNew/CMS收集器:

CMS:关注用户停顿时间
ParNew采用的复制算法,使用多线程并行的方式可以提高处理速度,CMS采用的是单线程的标记清理算法,而且老年代回收次数较少,使用单线程减少线程切换的资源消耗。
CMS的垃圾回收过程分为4个阶段:初始标记,并发标记,重新标记,并发清理。

  • 初始标记:进入STW,标记GCroots能直接关联的对象
  • 并发标记:不用STW
  • 重新标记:(多线程)进入STW,修改并发标记时程序执行导致的记录产生变动的标记
  • 并发清理:删除标记阶段判断已经死亡的对象;(由于不用进入STW,可以和用户线程并发)。

在清理期间,如果内存不够(清理线程和用户线程并行),会触发Concurrent Mode Failure,启用SerialOld进行垃圾回收
优点:

  1. 并发收集
  2. 低延迟

缺点:

  1. 产生内存碎片
  2. 对CPU资源敏感
  3. 无法处理浮动垃圾(并发标记阶段产生的新的垃圾对象)

    Parrallel回收器:吞吐量优先

    高吞吐量-》高效利用CPU时间,适合大量计算的任务
  • Parallel Scavenge工作在新生代,采用复制算法,采用多线程并行回收。
  • Parallel Old工作在老年代,采用标记整理算法,采用多线程并行回收的方法

G1垃圾回收器

  1. 为什么叫G1:垃圾回收的时候优先回收垃圾多的Region
  2. G1特点:将堆空间划分为等大的Region,单个大小约为2的整数次幂M,每个Region可以视为伊甸园区、survival区等区域,还有一个H区域,当对象大于0.5个Region时就存放到H区。在区域之间的垃圾回收算法可以视为:复制算法,整体可以视为标记整理算法。
  3. GC流程:
    1. 年轻代GC:并行独占式收集,将Eden区的存活对象移动到Survivor区或者老年区。
    2. 老年代并发标记过程:堆内存使用超过45%时启动。
    3. 混合回收:年轻代区域和老年代区域一同回收。同时老年代只收集部分老年代Region。
    4. FullGC(如果需要,作为保底机制存在)

首先分配Eden区的region,垃圾回收之后会产生Surivivor区。之后可能Survivor区直接升级为Old区。

  1. RememberSet:主要是解决一个对象被不同区域引用的问题,为了避免全堆扫描,每个区域都有一个RememberSet,在写入引用对象的时候使用写屏障。检查引用对象和被写入对象是否在同一个region,如果不在同一个region,就把相关引用信息写到被引用对象的rememberSet里面。这样做可达性分析的时候,就可以直接读取RSet,避免全局扫描。

三色标记法

用于标记出哪些对象是存活的,哪些对象是垃圾。
将对象分为三种颜色:

  • 白色:未访问
  • 黑色:当前对象已访问,且本对象引用到的其他对象也全部访问过了。
  • 灰色:本对象已访问过,但是本对象引用到其他对象尚未全部访问,全部访问过了再切成黑色。

    流程

  1. 一开始所有对象都在白色集合中。
  2. 初始标记:标记GCRoots直接相连的对象,将这些对象移到灰色集合中
  3. 之后就处理灰色集合,将所有引用的节点移到灰色集合中,然后将当前节点移到黑色集合。
  4. 重复步骤三,直到灰色集合为空。
  5. 结束后,仍未白色集合的对象即为GCRoots。

多标

标记期间,原本可达的对象变为不可达,但是之后的节点可能已经进入灰色或者黑色节点。
这些后面的节点就是浮动垃圾,这些只能在下一次标记中被发现。
还有并发标记之后开始的新对象,通常的做法是全部标为黑色,也算浮动垃圾。

漏标-读写屏障

标记期间,在黑色节点中又新增了引用,同时灰色对象中没有指向新对象的引用,导致无法被发现,出现漏标。
CMS采用写屏障+增量更新,在向黑色节点新增节点的时候,使用AOP的方法,新增GCROOTS指向该新增节点。
然后在重新标记的时候采用增量更新,扫描新增的GCROOTS解决漏标问题。