一、垃圾回收的几种方式
1、手动delete内存的方式回收垃圾
2、通过引用计数的方式,常见的有:ARC、智能指针
3、通过可达性的方式
二、编译原理主要讲述的是通过可达性的方式
这里有几种算法来进行垃圾回收
1、标记 清扫的垃圾回收方式
思想是:通过根集遍历所有能够 达到的空间进行标记,其他未被标记的空间则被标记为不可达(不可达则为free的空间)
这个算法有个特点是 :1、遍历的过程中如果曾变者在节点A已经扫描完之后再增加A的子节点B,那么就会出现B被额外删除的情况;2、在清扫阶段都要遍历所有的堆区,导致时间消耗会很长
如上是标记清扫的算法,从根集出发标记能访问到的所有对象然后遍历所有的内存对象将无标记的对象设置为free;
假设A已经被设为可达并且已经从Unscanned列表中删除,此时增变者创建了一个对象B被A引用那么在清扫阶段则会被删除从而早层误删的情况
2、对标记清扫的优化
思想是:在创建对象的时候将该对象设为unreashed, 在标记阶段把扫描到的对象都从unreached中移除,在清扫 阶段则 Free=Free U unreached; 然后将扫描到的对象复制给unreached
这个算法优化了第一点中的清扫阶段消耗时间长的问题
如上是标记清扫的优化,假设当前已经申请的对象已经都记录在了unreached, 那么最终标记完之后剩余的unreached对应一定是垃圾
第九行把扫描到的赋值给unreached使之能够用在在下一轮的清扫中
3、标记压缩的垃圾回收器
如上的算法上面在进行多次标记清扫之后可能会产生很多的碎片,为了减少碎片我们需要将可达的对象尽可能的放在一起
思想是:先对可达的对象进行标记,然后假设整个堆是空的,从低到高顺序遍历每个可达的对象并使用一个表记录这些可达对象所在的堆区位置并将即将分配给该可达对象的新的地址位置,在记录表完成之后;再次从低端开始拷贝每个对象到新的地址
如上8~12行所示是为了建立一张表用来记录从旧的位置到新的位置的映射,这一步只是建表无实际的拷贝操作
如上13~17行所示,先将对象中的引用设置为映射表中新的位置,然后将旧的对象全部拷贝到新的位置;这里是按顺序从低端开始遍历并且新的堆区在映射表中也是从低端开始分配,所以不会出现还未拷贝的对象被覆盖的现象
因为根集没有参与重新映射,所以只需要把根集中的每个引用设置一下即可
标签:遍历,清扫,标记,对象,回收,编译,垃圾,unreached From: https://www.cnblogs.com/czwlinux/p/16590191.html