GC与内存分配

判断对象死亡?

引用计数器(了解)

原理

给对象添加一个应用计数器,有引用+1,没引用-1
难以解决对象之间循环引用问题

可达性分析算法(GC_Root)\

原理

通过一系列的称为"GC ROOTS"的对象做为起始点,从这个节点开始向下搜索,
搜索所走过的路径称为引用链(Reference Chain)
当一个对象到GC_Root没有任何引用链相连(也就是从GC Roots到这个对象不可达)
则证明这个对象不可用

GC Roots

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

补充知识

如何描述这一类:内存足够的时候,希望保留在内存,内存不够的时候,抛弃这些对象

Strong Reference    强引用
Soft Reference        软引用        
Weak Reference        弱引用
Phantom Reference    虚引用

生存还死亡?

如果对象在进行可达分析后没有发现GC Roots连接的引用链,
则会被第一次标记,且进行一次筛选,筛选条件是此对象是否有必要执行finalize(),
当对象没有覆盖finalize()活着finalize()已经被虚拟机调用过,则虚拟机认为没必要执行??what

如果有必要finalize(),
则把这个对象放在一个F-Queue,并稍后由一个虚拟机 的 Finalizer线程去执行他的 finalize()


finalize()是对象逃脱死亡命运的 最后一次机会,稍后GC对F-Queue中的对象进行第二次小规模标记,
只要对象在finalize()中拯救自己,即可避免回收

扩展知识

安全点

垃圾收集算法

标记_清除算法

标记->清除
不足:
    1.效率问题:标记和清除两个过程效率都不高
    2.空间问题:标记清楚之后会产出大量的空间碎片

复制算法

原理

讲内存等分两份,每次只使用其中一份,当使用的这块内存用完了,就想这个内存上的对象复制到另一块上,然后清空
有点:
    效率高
不足:
    内存只能使用原来的一半

新生代

新生代采用此算法

8:1:1
|            eden            |    survivor_to    |    survivor_from    |

每次只是用eden和survior中的一块,当回收时,直接讲使用的两块复制到另一块未使用的survivor
可见回次回收的都是不多于10%的对象,可以存活
新生代:老年代 默认比例 1:3
当survior空间内存不够,需要依赖其他内存,也就是老年代的内存担保

标记-整理算法

复制收集算法在对象存活比例较高的时候要进行较多的复制操作,效率将会变低
更关键的是,如果不想浪费50%的空间,就需要额外的空间进行分配担保,所以老年代不能采用这种

根据老年代的特点,提出了 "标记-整理":
标记之后让所有存活的对象向一段 端移动,然后直接清理掉端边界外的内存.

垃圾收集器

概览

11

新生代垃圾回收器

1.Serial垃圾收集器

采用串行单线程的方式完成GC 任务,Stop the Word!
采用复制算法:
    young generation 标记-复制
    old   generation 标记-整理

适合客户端模式

2.ParNew

是Serial的多线程版本,需要线程切换,依旧Stop the word!
多核CUP的情况下,比Serial高效!缩短GC时间

3.Parallel Scavenge

Parallel Scavenge和parNew一样都是并行的多线程的新生代收集器,都使用"复制"算法进行垃圾回收
也称"吞吐量优先"收集器
异常点:
ParNew收集器追求降低GC时用户停顿的时间,适合交互式应用,良好的反应速度提升用户体验
Paraller Scavenge追求可控的CPU 吞吐量,能够在较短的时间完成指定的内容,适合不需要太多交互的后台运算

吞吐量:用户线程运行时间/CPU总时间(用户线程运行时间+GC线程运行时间)
可以自适应调节策略

老年代垃圾回收

1.Serial Old

Serial的老年代版本,使用"标记-整理"算法,主要应用Client模式下

2.Parallel Old

Parallel Scavenge的老年代版本

3.CMS

低延迟:用户线程和GC线程并发执行

由于CMS采用"标记-清除"算法,因此会产生大量的空间碎片.为解决这个问题
-XX:+UserCMSCompactAtFullCollection
强制JVM在FGC完成后对老年代压缩,执行一次空间碎片  整理,同时会引发STW
-XX:+CMCFullGCsBeforeCompaction=n
执行n次FGC后,JVM再在老年代执行空间碎片整理

CMS过程:

过程:
->初始标记      STW
->并发标记
->重新标记
->并发标记

CMS缺点:

- 由于CMS在GC过程用户GC线程并行,从而有线程的额外开销
- 内存碎片化的问题
- 无法处理浮动垃圾,导致频繁FGC

4.G1

提供了三种垃圾回收模式:YoungGC MixGC FullFC,在不同条件下触发 设计原则就是简化jvm性能调优

  1. 开启G1收集器
  2. 设置堆的最大内存
  3. 设置最大的停顿时间

Humongous区域:存放巨型对象(>50% region)

原理

最大的区别是取消了年轻代,老年代的物理划分,取而代之的是将堆分为若干区域

内存分配

内存分配规则

对象优先在Eden分配,如果Eden没有足够空间进行分配.虚拟机将发起一次MinorGC
如果这个MinorGC发现 survivor空间不够,无法放入,则 通过 分配担保 转移到老年代
老年代不够,则majorGC

补充

- 1.大对象直接进入老年代
- 2.长期存活的对象晋级到老年代
- 3.动态对象年龄判定{如果Survivor空间中相同年龄的所有对象的大小等于Survivor的一般,年龄等于活着大于的对象可以之间进入老年代}
- 4.空间分配担保: HandlePromotionFailure(允许风险,则minorGC,不允许,直接FullGC)

results matching ""

    No results matching ""