java 自动内存回收机制_开源一个blink里的C++垃圾回收器,让你的C++也拥有java那样的自动回收机制,无需担心内存泄漏和循环引用...

blink gc是一个有趣的组件,从blink/chromium里抽离出来,目的是让C++也有GC机制,这不是异想天开,而是blink的oilpan项目,在享受GC的同时,还能提升性能。

blink gc能让C++拥有java一样的垃圾回收机制,只要按照规范,让你的类继承 blink gc规定的基类,并且写上trace函数,就能拥有自动垃圾回收能力,并且无需担心 智能指针那种循环引用引起的无法回收。

本次提交带了个简单的测试用例,稍后补充更完整的。

例子里可以看到,new 一个新对象,然后完全没管他就返回了。然后在blink::Heap::collectAllGarbage();里神奇的销毁了这个对象。

本次发出的代码,就是从blink里抽离的oilpan项目。这东西本来是和blink、WTF紧密关联的,但我把无关部分去掉,并整理了下目录结构发了出来,可以比较容易的嵌入到你的工程之中。

这个blink gc还是可以跨线程回收内存的。

再补充一下,我认为C++垃圾回收器对绝大部分C++工程都是非常有必要实现的,而且比智能指针不知道好用到哪里去了。

智能指针和回收器,在C++里使用,都需要遵循一些规则。但智能指针,有好几个问题:

1,智能指针的种类太多,而且每种指针潜规则太多,稍不注意就会着道。

2,智能指针不注意使用的话,会引发循环引用。别说什么小心点就没事。问题是如果团队合作的话,每个人很难知道你的指针在别人的地盘到底怎么指向的,要小心避开简单的循环引用简单,如果循环引用的是一个很大的环,稍不留神就容易中招。这点从chromium的经验来看就知道。chromium的开发基本都是大牛不必说了吧,就这样还是各种循环引用导致内存泄漏。

另外,智能指针和C++回收器都需要使用前假定开发人员了解一些使用规则。但智能指针是每次申请、使用、传递,都需要小心了解使用规则、并小心避免循环引用。这个需要注意的心智开销的规模,是随着工程的增加而不断增加。而回收器只需要在定义的时候小心使用规则即可。相比之下,程序员的心智负担开销小的多。

最后,回收器会占用一些时间回收垃圾造成顶停顿,但根据目前使用经验来看,绝大部分不是那么注意性能的工程都可以接受。毕竟大部分工程在运行时大部分时间都是空闲的。

Oilpan项目引入的背景是,Chromium在浏览网页时,有时会发生莫名奇妙的内存泄露问题。根据Blink的内存泄露检测器(LeakDetector)给出的数据显示,ChromiumWebView在访问946个网站之后,有294个WebCore::Document对象没有得到释放。

在Oilpan项目之前,Blink和Chromium都采用引用计数技术(referencecounting)来管理内存,每个对象内部都一个引用计数,表明当前对象被引用了多少次,当引用技术归零时,对象就会被自动释放掉,这种方式一直以来都存在一个缺陷就是循环引用问题,就A引用了,B又引用了A,最后导致A和B都没有机会释放,此外,C++中启用引用计数还存在其他几个方面的问题:引用计数器的增减开销问题;

C++中可以通过Raw指针轻易地绕开RefPtr的管理,一旦使用不当,将导致use-after-free内存错误,存在安全问题;

尽管引用计数存在上述一些问题,但它很轻量级,仍然是C++程序中广泛使用的自动内存管理计数。Blink项目并不满足这种轻量级的内存管理方法,于是Oilpan项目提上日程,要实现对Blink对象的自动回收机制。比起引用计数技术,Oilpan垃圾回收器确实是个庞然大物,它实现了一个一般只有虚拟机才需要的高级特性,然而Blink项目力求精益求精,追求最好!

Oilpan实现了一种跟踪式的垃圾回收机制,具有如下特点:Blink中所有的对象都将分配在一个受托管的堆中,每个对象都提供了一个trace的方法,用来建立与堆中其他对象的可达关系,因此,从根节点(一般DOMWindow)出发,Blink的对象在托管堆中形成了一个对象图,那些由根节点不可达的对象将会被GC掉,这样就避免了循环引用问题。

Oilpan的GC并不会随时都发生,它会被推迟到消息循环中执行,因为当消息循环执行完任务队列中最后一个任务时,此时Blink的栈为空,没有在栈中分配的对象了。

一旦需要执行GC时,Blink首先要确保所有运行的线程到达了一个“安全点”,不会再分配新的对象,然后从根节点出发,计算堆中所有对象的传递可达性,并标记(mark)所有可达的对象,最后每个线程开始清理(sweep)属于自己的那部分堆空间,回收所有未被标记的对象,将其插入到空间列表中。

与V8引擎的GC相比,Oilpan的GC会牵扯到Blink所有的线程,Database线程,File线程等等,所有的线程都共享一个Oilpan的堆空间。

Oilpan提供了两个超类GarbageCollected和GarbageCollectedFinalized,来保证它们的子类都分配在由Oilpan管理的堆中。

截止到目前,Oilpan基础框架已经比较稳定,modules/中所有对象默认都启用了Oilpan,但Node层次结构还未正式启用。

关于Oilpan,大家可能比较关心它的性能和内存开销问题,评价Oilpan是否成功有三点,第一,比引用计数更快,第二,不能使性能变差,第三,不会增加内存使用量的峰值。根据最新的性能和内存使用评测结果来看,执行效率和内存使用的峰值都不是问题,但因GC带来的暂停时间是个问题,特别是对于一些动画的benchmark,在Nexus7设备上有些GC操作要花费超过50ms,显然是不能接受的,下一步的方向就是优化stop-the-world所耗费的时间。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值