GC

什么是垃圾回收

  程序运行会产生各种各种的数据,那么这些数据存在于内存当中

  这些数据不可能是永久存在的,无效的资源对象需要进行垃圾回收,释放内存

为什么需要垃圾回收机制

  如果不进行垃圾回收,内存迟早都会被消耗空,因为我们在不断的分配内存空间而不进行回收

  除非内存无限大,我们可以任性的分配而不回收,但是事实并非如此。所以,垃圾回收是必须的

哪些内存需要回收

  哪些内存需要回收是垃圾回收机制第一个要考虑的问题

  所谓“要回收的垃圾”无非就是那些不再被任何途径使用的对象

不同的编程语言都有GC垃圾回收

  java语言自带GC垃圾回收器,并且有JVM自动进行垃圾回收,程序员主要关注代码实现,不关注垃圾回收 System.gc();

  C/C++语言当中,程序员new一个对象,相当于申请了一块内存,如果需要释放资源得手动通过delete关键字进行内存的释放
垃圾回收算法

  如果使用的算法不合理,反倒会造成资源的浪费,垃圾回收常见算法

引用计数法

  原理:假如有一个对象A,任何对象对A对象的引用,计数器就+1,当引用失效或者失败时计数器-1

  如果对象A的计数器为0,GC就会当成对象没有引用了,就会将该对象回收

标记清除法

  标记:从根节点开始标记引用对象

  清除:未被标记的对象就是垃圾对象,可以清除

   原理:初始状态下所有对象的标记都为0,当内存不足的情况下,

  标记阶段:GC先会进行标记阶段,从根节点开始,凡是引用的对象都标记为1,其他没有引用的对象标记为0

  清除阶段:凡是对象标记为1代表该对象存在引用不清除,对象标记为0则清除,清除完毕之后所有对象重新标记为0

  

   缺点: 

    效率较低,标记和清除两个动作都需要遍历所有的对象,并且在GC时,需要停止应 用程序,对于交互性要求比较高的应用而言这个体验是非常差的。
    碎片化较为严重,可能导致大数据没有办法存储,小数据存储浪费空间

标记压缩算法
  同标记清除法相同,标记过程相同,在清除过程中,先将垃圾对象压缩到内存末尾,然后再清除

  

   缺点:对象需要移动,效率有一些影响


复制算法

  内存被分为大小相同两块区域,一块为From,一块为To,程序向From区域存放数据,当From数据即将满了的情况下,进行垃圾回收

  首先标记垃圾对象,然后将没有标记的对象复制到To当中,然后回头将From所有区域清空,然后角色交换,From和To交换,保证To永远为空

  

  年轻代当中分为Eden区和From区和To区,其中From和To区的大小时相同的,程序向Eden去和From区存放数据,当数据即将满了的情况下

  Eden区会将活跃对象存放到To区,From区会将年龄小的对象存放到To区,那么年龄大的存放到Old年老代区域当中

  清空Eden去和Old区的所有数据,然后将From区角色和To区角色互换,这样保证To区为空

  当垃圾回收机制反复运行时,那么To区可能数据饱和,如果数据饱和则将所有对象转移到Old年老区

分代算法

  

  合适的垃圾回收对象沿用合适的算法,在JVM当中年轻代适合复制算法,年老代可以标记清除发,或者标记压缩算法

  现代商用虚拟机基本都采用分代收集算法来进行垃圾回收。

  这种算法没什么特别的,无非是上面内容的结合罢了

  根据对象的生命周期的不同将内存划分为几块,然后根据各块的特点采用最适当的收集算法。

  大批对象死去、少量对象存活的(新生代),使用复制算法,复制成本低

  对象存活率高、没有额外空间进行分配担保的(老年代),采用标记-清理算法或者标记-整理算法。

原文地址:https://www.cnblogs.com/whtt/p/12420983.html