JVM内存回收策略(GC)

1.静态内存分配和回收

    静态内存空间是在Java栈上分配的(编译时就确定的),当这个方法结束的时候,对应的栈帧也就取消,且静态内存空间也就回收了(针对栈帧而言)。

2.动态内存分配和回收

    JAVA中对象的内存空间是动态分配的,所谓的动态分配就是在程序执行时才知道要分配的存储空间大小,而不是在编译时就能够确定的。

    针对堆中对象什么时候不被使用,又如何来回收它们,这正是JVM的一个很重要的组件-----垃圾回收器要解决的问题。


垃圾检测的算法:

    1.引用计数算法

    2.可达性分析法

垃圾回收算法:

1.基于分代的垃圾回收算法

        该算法设计思路:把对象按照寿命长短来分组,分为年轻代和年老代,新创建的对象分在年轻代,如果对象经过几次回收之后依然存活,那么再把这个对象划分到年老代。年老代的收集频率不像年轻代那么频繁,这样就减少了每次垃圾收集需要扫描的对象个数,从而提高了垃圾回收的效率。

    这种思路是把堆划分成了若干个子堆,每个子堆都对应一个年龄代。

            分别是:    (1)新生代(Young区)其中Young区又分为Eden区和两个Survivor区。

                               (2)老年区(Old区)

                               (3)永久区(Perm区)

    Young区又分为Eden区和两个survivor区,其中所有新创建的对象都在Eden区,当Eden区满了之后会触发minor GC将Eden区仍然存活的对象复制到其中一个Survivor区中,另外一个Survivor区中的存活对象也复制到这个Survivor中,以始终保证有一个Survivor区是空的。如果Survivor区也满了,GC收集器会将这些对象直接存放到Old区。如果在Survivor区中的对象足够老,也会被直接放到Old区。最终OLD区也满了的时候,就会出发Full GC,直接回收整个堆内存。

Perm区存放的是Class对象和ClassLoader。如果Perm区满了,同样触发Full GC。

SUN官方建议:Young区大小为整个堆大小的1/4

Young中的Survivor一般为整个堆大小的1/8

总结:当OLD区满了的时候和永久区满了的时候就会触发FULL GC.

2.标记-清除算法:

标记过程:引用计数法,可达性分析

CMS收集器就采用此算法,缺点是会产生大量的不连续的内存碎片,不利于后续装入大对象的操作。

3.复制算法:

    把容量分成相同两个部分,每次使用其中一块,当其中一块用完了,复制对象到另一块上面去。现在的虚拟机大多使用这个方法来手机新生代中的对象,到survivor区中。


4.标记-整理算法

    标记过程:引用计数和可达性分析

    整理算法不是对可回收对象进行清理,而是把对象都向一端移动,然后直接清理掉端边界以外的内存。





4.Hotspot提供了6个垃圾收集器:

1.Serial 收集器(Client模式下默认):

    是单线程的新生代垃圾收集器

    新生代采用复制算法暂停所有用户线程。

    老年代采用标记-整理算法暂停所有用户进程。

2. ParNew 收集器

    是上面Serial收集器的多线程版本,在单CPU下表现不如Serical 收集器

3.Paralllel Scavenge 收集器

    和ParNew类似,目的是达到可控制的吞吐量,可以指定吞吐量大小时间

4.Serical Old收集器

    Serial Old是Serial收集器的在老年代的版本,同样是单线程

5. Parallel OLD 收集器

    同样是Parlllel Scavenge收集器的老年代版本

6. CMS (Concurrent Mark Sweep)收集器

    CMS收集器是一种获取最短回收停顿时间为目标的收集器。

    基于 标记-清除 算法实现


Eden(新生代中的一部分):对象优先在Eden中分配,当Eden没有足够空间进行分配的时候,虚拟机将发起一次MinorGC.

老年代:大对象直接进入老年代,长期存活的对象将进入老年代。

Minor GC:一般当新对象生成,并且在Eden申请空间失败时,触发。将清除Eden区的非存活对象,并把存货对象移动到Survivor,然后整理两个Survivor区。该方式不会影响到老年代,此外,该GC推荐使用速度快,效率高的算法,使Eden区尽快空闲出来。

Full GC:对整个堆进行整理,包括Young、Tenured和Perm,因此为了提高系统性能,需要减少FullGC的次数。发生FullGC的场景有:年老代写满,持久代被写满和System.gc()被显示调用,上一次GC后Heap各域分配策略动态变化。

    

你可能感兴趣的:(JVM内存回收策略(GC))