JVM 垃圾回收机制

来源:互联网 发布:淘宝卖家寄快递 编辑:程序博客网 时间:2024/06/05 09:15

一、什么是垃圾

    当一个对象的引用不在使用,但仍占用内存空间时,则被认为是垃圾对象。

二、怎么判断垃圾对象

    1、引用计数器算法

    当创建对象的时候,为这个对象在堆栈空间中分配对象,同时会产生一个引用计数器,同时引用计数器+1,当有新的引用的时候,引用计数器继续+1,而当其中一个引用销毁的时候,引用计数器-1,当引用计数器被减为零的时候,标志着这个对象已经没有引用了,可以回收了!这种算法在JDK1.2之前的版本被广泛使用,但是随着业务的发展,很快出现循环引用问题。

    2、根搜索算法

   根搜索算法是从离散数学中的图论引入的,程序把所有的引用关系看作一张图,从一个节点GC ROOT开始,寻找对应的引用节点,找到这个节点以后,继续寻找这个节点的引用节点,当所有的引用节点寻找完毕之后,剩余的节点则被认为是没有被引用到的节点,即无用的节点。

      目java中可作为GC Root的对象有

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

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

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

    ④本地方法栈中引用的对象(Native对象)


三、什么时候进行垃圾回收

   1、JVM自己决定什么时候垃圾回收(由四给出的算法机制决定)。
    2、程序员人为的触发System.gc()方法,向系统发出垃圾回收请求,但最终是否回收,由系统决定。
    注意:Java提供finalize()方法,为了释放“特殊”内存区域(非new获得的区域),Java允许类定义一个finalize()方法,垃圾回收器释放对象时,将首先调用其finalize()方法。


四、通过什么算法垃圾回收

    1、标记-清除算法

    标记-清除算法采用从根集合进行扫描,对存活的对象对象标记,标记完毕后,再扫描整个空间中未被标记的对象,进行回收。标记-清除算法不需要进行对象的移动,并且仅对不存活的对象进行处理,在存活对象比较多的情况下极为高效,但由于标记-清除算法直接回收不存活的对象,因此会造成内存碎片!


    2、复制算法

    复制算法采用从根集合扫描,并将存活对象复制到一块新的,没有使用过的空间中,这种算法当控件存活的对象比较少时,极为高效,但是带来的成本是需要一块内存交换空间用于进行对象的移动。


    3、标记-整理算法

    标记-整理算法采用标记-清除算法一样的方式进行对象的标记,但在清除时不同,在回收不存活的对象占用的空间后,会将所有的存活对象往左端空闲空间移动,并更新对应的指针。标记-整理算法是在标记-清除算法的基础上,又进行了对象的移动,因此成本更高,但是却解决了内存碎片的问题。


    4、基于新生代---年老代的算法

    JVM将堆分为Young区、Old区和Perm区
    Yong区:又分为Eden区和两个Survivor区,新创建的对象都在Eden区,当Eden区满时,触发minor GC将Eden区仍存活的对象复制到一个Survivor区,另一个Survivor区存活的对象也复制到这个Suevivor区,为了保证始终有一个Survivor区是空的。
    Old区:存放的Young区的Survivor满后,又有对象要加入Survivor区,则GC收集器将Survivor区的对象直接放到Old区。如果Survivor区中对象足够老,也存放到Old区。如果Old区满了,则触发Full GC,回收整个堆内存。
    Perm区:存放的主要是类对象,如果一个类被频繁的加载,也会导致Perm区满,Perm区回收也是Full GC触发。



0 0