深入理解java虚拟机

时间:2023-01-02 13:19:30

1、概述

2、对象已死吗?

引用计数器

  给对象添加一个引用计数器,每当有引用时,计数器加1,引用失效时,计数器减1;任何时刻计数器为0的对象就是不可能再被使用的。

  若对象是循环引用,则无法处理。JVM不使用。

可达性分析算法

  通过一系列的称为“GC Roots”的对象作为起始点,从这些节点开始向下搜索,搜索所经过的路径称为引用链(Reference Chain),当一个对象没有任何引用链相连时,表明该对象不可用。

  Java语言中,可作为 GC Roots的对象包括如下:

    虚拟机栈(栈帧中的本地变量表)中引用的对象。

    方法区中类静态属性引用的对象。

    方法区中常量引用的对象。

    本地方法栈中JNI(即一般说的Native方法)引用的对象。

Java中的引用:

  强引用(Strong Reference) 类似“Object obj=new Object()”,这类的引用,只要强引用还存在,对象永远不会被回收。

  软引用(Soft Reference)用来描述一些还有用但并非必需的对象。在系统将要发生内存溢出前,会对这类对象进行回收;如果这次回收还没有足够的内存,才会抛出内存溢出异常。SoftReference类来实现。

  弱引用(Weak Reference) 非必需的对象,但强度比软引用更弱一点。当垃圾收集器工作时,无论内存是否够用,都会回收这类引用。WeakReference来实现。

  虚引用(Phantom Reference)幽灵引用或幻影引用,最弱的一种引用关系,完全不对其生存时间构成影响,也无法通过虚引用来取得一个对象实例,唯一目的就是能在这个对象被收集器回收时收到一个系统通知,用PhantomReference来实现

 

3、垃圾收集算法

标记清除算法 Mark-Sweep

  首先标记出所要回收的对象,在标记完成后统一回收所有被标记的对象。可能会造成碎片。

复制算法Copying

  将可用内存按容量划分为大小相等的两块,每次中使用其中的一块,当这一块用完了,将存活的对象复制到另一块中,然后把已使用的一块清空。

     每次对整个半区进行内存回收,也不用考虑内存d碎片;代价为只使用了内存的一半。

  现在商业虚拟机都使用这种算法来回收 新生代,不过将内存分为较大的Eden和两块较小的Survior,每次只使用Eden和一块Survior,回收时一次复制到另一块Survivor,默认比例8:1:1.

标记-整理算法

  与 标记-清除算法一样,但是后续步骤是让所有存活的对象都向一端移动,最后直接清理掉端边界以外的内存。

分代收集算法 Generation Collection

  根据对象存活周期的不同将内存划分为几块

深入理解java虚拟机

默认的,新生代与老年代的比例值为1:2(可以通过参数-XX:NewRatio来指定

 Eden:from:to=8:1:1可以通过--XX:SurvivorRatio来指定

4、HotSpot的算法实现

枚举根结点

  从可达性分析中从GC Root节点找引用链的操作中,需要停顿所有Java执行线程(Stop The World, STW)。HotSpot的实现中使用一组称为OopMap的数据结构来实现,当执行系统停顿下来后,并不需要一个不漏的检查所有执行上下文和全局的引用位置。

安全点

安全区域

5、垃圾收集器

 Serial收集器

  单线程的收集器,必需暂停其他所有的工作线程,简单而高效。

ParNew

  Serial的多线程版本,暂停其它工作线程,启用多个回收线程来回收。

Parallel Scavenge收集器

  目标是达到一个可控制的吞吐量,吞吐量就是Cpu运行用户代码的时间和CPU总消耗时间的比值。

Serial Old收集器

  Serial收集器的老年代版本。

Parallel Old收集器

  老年代的Parallel Scavenge收集器,使用多线程和“标记-整理”算法。

CMS收集器 Concurrent Mark Sweep

  以获取最短回收停顿时间为目标的收集器

    初始标记 (CMS initial mark), Stop the World,只是标记一下GC Roots能直接关联到的对象,速度很快

    并发标记(CMS concurrent mark),进行GC Roots Tracing的过程。

    重新标记(CMS remark), Stop the World, 为了修正并发标记期间因用户程序继续运作而导致标记产生变动的那一部分对象的标记记录

    并发清除(CMS concurrent sweep)

G1收集器 Garbage-first

   面向服务端应用的垃圾收集器

  1、并发与关行。 充用利用多CPU、多核环境下的硬件优势,来缩短Stop-The-World从停顿的时间,可以通过并发的文萃上java程序继续执行

  2、分代收集。 分不同的方式去处理新创建的对象和已经存活了一段时间、熬过多次GC的旧对象

  3、空间整合。从整体来看是基于“标记-整理”算法的收集器,从局部上来看是基于“复制”算法实现的, 运行期间不会产生内存碎片,收集后能提供规整的可用内存。

  4、可预测的停顿

 

Young Generation: Serial、ParNew、Parallel Scavenge、G1

Tenured(old) Generation:CMS、Serial Old、Parallel Old

 

6、内存分配和回收策略

  对象优先在Eden分配,当Eden区没有足够空间分分配时,触发一次GC

  大对象直接进入老年代

  长期存活的对象进行老年代

    虚拟机给每个对象定义了一个对象年龄计数器,如果对象在Eden出生并经过第一次MinorGC后仍然存活,并且能被Survior容纳的话,将被移动到Survivor空间中,并且对象年龄为1.

    对象在Survivor中每一次Minor GC,年龄增加1,当年龄增加到一定程序,就晋升老年代

   动态对象年龄判定

    为了更好地适应不同程序的内存状态,如果在Survivor空间中相同年龄所有对象大小的总和大于Survivorp空间的一半,年龄大于或等于该年龄的对象可以直接进入老年代

  空间分配担保