jvm学习笔记(3)——java对象的内存分配和对象的回收(GC)

引言:    

    之前的文章已经提过,java对象实例是存放在堆上的,至于是在伊甸区、存活区还是老年区,这些都是从对象回收(GC)角度来进行的逻辑划分。所以我们先说对象的回收(GC),然后再依据GC的策略来说明新的对象具体在哪个区生成。

 

GC(Garbage Collection):

    垃圾回收,指的就是jvm占用内存的回收。那么需要回答3个问题:

  • 哪些内存需要回收?——>可达性分析算法。
  • 什么时候回收?——>简单的来说,伊甸区的空间不足发生新生代GC(Minor GC),老年代空间不足的时候发生老年代GC(Major GC / Full GC)
  • 如何回收?——>通过垃圾回收器,jdk8默认的是UseParallelGC(PS scavenge + Serial Old),还有UseConMarkSweepGC(ParNew + CMS + Serial Old),以及UseG1GC(G1)。

 

1、可达性分析算法:以一系列成为“GC Root”的对象最为起始点,当一个对象没有到达GC Roots的引用链条,就判定这个对象为可回收的。

    GC Roots对象:

  • 虚拟机栈(栈帧中的本地变量表)中引用的对象。
  • 方法区中类静态属性引用的对象。
  • 方法区中常量引用的对象。
  • 本地方法栈中JNI(即Native方法)引用的对象。

2、垃圾收集算法(分代收集):

  • 新生代,对象存活率较低,复制算法。
  • 老年代,对象存活率较高,标记-整理算法、标记-清除算法。

3、垃圾收集器:

新生代收集器:

  • Serial收集器:采用“复制”算法,暂停用户线程,单线程收集。
  • ParNew收集器:采用“复制”算法,暂停所有用户线程,采用多线程并行收集。和CMS老年代收集器搭配使用。关注点:GC时用户线程的停顿时间。
  • Parallel Scavenge收集器:采用“复制”算法,和ParNew收集器类似,但关注点不同。关注点:高吞吐量。

老年代收集器:

  • Serial Old 收集器:采用“标记-整理”算法,暂停用户线程,单线程收集。和Parallel Scavenge收集器搭配使用。
  • Parallel Old收集器:采用“标记-整理”算法,暂停用户线程,多线程并行收集。和Parallel Scavenge收集器搭配使用。
  • CMS(Concurrent Mark Sweep)收集器:采用“标记-清除”算法,不暂停用户线程,多线程并发收集。与ParNew收集器搭配使用。

新一代收集器:

    G1(Garbage-First)收集器:

  • GC工作时为并行,GC与用户线程为并发;
  • 可独立管理整个GC堆,不需要与其他GC收集器配合使用;
  • 空间整合:整理上看是“标记-整理”算法实现的,从局部(两个Region之间)上看是基于“复制”算法实现的。

总结:

  1. ParallelScavenge关注的是高吞吐量;
  2. CMS关注的是低停顿时间;
  3. G1关注的是使用时间相对较短的停顿来达到很高的吞吐量,CMS的替代品,在超大堆上表现优异(eg:8g以上)。

4、GC发生时间:

    (1)MinorGC:大多数情况下,对象在新生代Eden区分配。当Eden区没有足够空间时,进行一次minorGC。如果是大对象,直接在老年代分配。

    (2)FullGC:

        a.系统主动调用System.gc(),不一定立即执行;

        b.老年代空间不足;

        c.方法区空间不足;

        d.通过Minor GC后进入老年代的平均大小大于老年代的可用内存;

        e.由Eden区、From Space区向To Space区复制时,对象大小大于To Space可用内存,则把该对象转存到老年代,且老年代的可用内存小于该对象大小。

 

参考资料:《深入JAVA虚拟机》

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章