java垃圾回收

java垃圾收集

  1. 首先我们来思考一下什么对象是垃圾需要被回收?

    1. 引用计数算法

      每个对象都会有一个整形值用来记录当前他被几个reference类型所持有,当该整型值为0时就表示该对象要被回收。这种回收算法有的明显问题就是存在循环引用的现象,比如A的一个Field是B,B的Filed是A,这样俩个对象就无法被正确判断并回收。

    2. 可达性分析算法

      从GC Root 对象开始所有可以被访问到的都是要被使用的,而剩下的对象就是要被回收的。

      而可以作为GC Root 的对象 包括如下几类:

      • 静态变量
      • 虚拟机中栈所引用的对象。注意:如果对象不存在逃逸的可能使用标量替换在栈上创建,这样效率很高,对象在堆上创建的一个主要原因是为了线程共享,如果不需要)
      • 常量
      • class对象

    当一个对象被标记为死亡时,垃圾回收就会尝试在第一次收集其时尝试调用它的finalize()方法,在这个方法中被回收的对象可以尝试自救,或者通知自己快被回收了。如果这个对象没有重写该方法就直接被回收,如果对象重写了该方法,就会再第二次的该对象被标记为死亡时回收。注意一个对象只有一次自救的机会,即使它第一次自救成功,如果它再次被标记为死亡就不会再调用该方法。

标记清除算法:

标记清除算法分为两个阶段:

  1. 标记阶段:

    使用可达性方式并使用深度优先遍历算法,将所有active对象标记为active。

  2. 清除阶段:

    将查看对象是否active不是的话就直接把它分片,并将地址添加到可用内存链表(可用空闲链表)上,这样分配对象,就直接从可用空闲链表上找合适大小的空间并分配。清楚阶段并不会将回收的内存全部置为0,将内存全部置为0应该在创建对象的阶段应该为:刚为对象分配完内存空间之后。

  3. 缺点:

    碎片化问题,对象分配速度

标记复制算法:

  1. 第一阶段类似:
  2. 不同的是,该收集算法会将内存分为两块,第二阶段会将正在使用的这块内存中未被收集的对象,复制并整齐排列到另一块大小相等的内存。
  3. HotSpot的实现是将新生代分为三块内存,分别为eden,survivor from,survivor to,碧莉为8:1:1,因为标记复制算法在存活对象比较少的时候效率很高,新生代中的对象又比较短命因此比较适合新生代的回收。当对象刚被创建时,分配在eden上(如果eden内存不够就直接分配在老年代),survivor from 中存放上次回收剩下的对象,本次的survivor from 也就是 上次的 survivor to。对象熬过的垃圾回收次数比较多就可能被弄到老年代。
  4. 优缺点:对象存活率低时比较高效,当时空间浪费也是明显的。(降低Survivor 的比例就是在减少空间浪费 )

标记整理算法:

标记阶段差不多,但是接下来就要将存活的对象,移向内存一边(紧密排列)

avatar

serial:采用串行的方式收集垃圾,会STW。parallelScavenge采用并行的方式收集垃圾但是仍然会STW。parNew,结合CMS和Serial进行收集垃圾。

原文地址:https://www.cnblogs.com/FCY-LearningNotes/p/14799770.html