cocos2d-js 浏览器与JSB内存管理机制的不一样

写这边文章的主要目的是为了理解使用cocos3d-js开发app时,浏览器调试与真机状况不一致的缘由程序员

1、浏览器中内存管理机制算法

  HTML5版本运行时,整个游戏只存在JS脚本与一些必要的资源文件,这时候内存管理是由JS内存管理机制来控制的。浏览器

  JS内存管理有一套很是智能的机制,称为垃圾回收器。垃圾回收器有两种策略--引用计数与标记清除,判断某个对象是否可回收,app

而后周期性启动回收线程把以前已标记为可回收的对象销毁回收。this

  引用计数:引用计数使用系统记录一个对象被引用的次数,当对象被引用的次数变为0时,该对象即被视做垃圾而被回收;spa

这是一种比较简单高效的策略,可是引用计数对循环引用的状况难以处理;这时候就引入了另外一种策略:标记清除线程

  标记清除:这样的方法是产生跟踪对象的关系图,而后进行垃圾回收。其算法是首先将程序中正在使用的对象视为“根对象”,3d

从根对象開始查找它们所引用的堆空间,并在这些堆空间上作标记,可是这种方法每每会产生比较大的计算开销;指针

  不断怎么说,JS的内存管理足够智能,使得程序员能够没必要关注内存管理,反而要关注如何让JS的内存管理机制可以搞高效的调试

运转。

2、JSB

  cocos2d-js在发布为app时,使用的是JSB,而JSB底层使用的是cocos2d-x,当代码运行时,就存在了两套运行环境--JS运行环境和Cocos2d-x

的镜像运行环境。项目的代码在JS运行环境中每添加一个节点,cocos2d-x中就会相应的添加一个相同的节点,可是这两个运行环境是不彻底

相同的,好比说内存管理机制:JS使用JS本身的垃圾回收机制,而cocos2d-x使用的是cocos2d-x本身的一套内存管理机制--智能指针的变种:

计数器机制(不是上方的引用计数)

  cocos2d-x为几乎全部的类添加了一个基类Ref类,这个类只有一个做用:管理cocos对象的计数,retain()计数加一,release()计数减一

若计数为零,则自动释放该对象(缘由以后解释)

  而支持cocos2d-x自动内存管理的类(Node、Action等)都存在一个方法Create(),这个Create中有两个要关注的点:new与autorelease();

在使用create时,会使用new一个对象,而且计数设为1(retain()),而后会调用autorelease(顾名思义会自动释放该对象,计数减一);

  如今来看看autorelease,它会将对象放入AutoreleasePool池中,有一个AutoreleaseManger来管理AutoreleasePool,在每一帧结束的

时候,AutoreleasePool中的对象会调用release,若计数为0,则会内释放,这样就实现了cocos2d-x的内存自动回收机制。

3、形成错误的缘由

  举个栗子:

let ball = new cc.Sprite(""); this.scheduleOnce(function(){ this.addChind(ball); }.bind(this),2);

这段代码在浏览器上时没有问题的,可是打包到手机上,就会出错。缘由很简单,new以后并无立刻addChind,这时候计数为一,一帧以后被清除,2s以后再去添加

就会找不到该对象。

这时候能够改为下面的代码

let ball = new cc.Sprite(""); ball.retain(); //计数加一
this.scheduleOnce(function(){ this.addChind(ball); ball.release() //计数减一
}.bind(this),2);