首页 > 代码库 > Android framework回顾 sp 和 wp sp对象
Android framework回顾 sp 和 wp sp对象
用如下代码说说我遇到的疑惑。
201 static sp<MediaPlayer> getMediaPlayer(JNIEnv* env, jobject thiz)
202 {
203 Mutex::Autolock l(sLock);
204 MediaPlayer* const p = (MediaPlayer*)env->GetIntField(thiz, fields.context);
205 return sp<MediaPlayer>(p); //(1)c++两种初始化对象方法。
206 }
413 static void
414 android_media_MediaPlayer_start(JNIEnv *env, jobject thiz)
415 {
416 ALOGV("start");
417 sp<MediaPlayer> mp = getMediaPlayer(env, thiz); //(2)重载的操作符 =
418 if (mp == NULL ) {
419 jniThrowException(env, "java/lang/IllegalStateException", NULL);
420 return;
421 }
422 process_media_player_call( env, thiz, mp->start(), NULL, NULL ); //(3)
423 }
sp是什么?
mp是sp<MediaPlayer>的对象,怎么的能调用到MediaPlayer的start函数呢?
sp就是个模板类。:
那mp怎么调用start()的呢?
查看sp源码类,就会发现sp类中重写了->, 使->指向成员变量m_ptr(T* 模板参数的对象,如MediaPlayer),
mp->的返回值是m_ptr,即返回的是MediaPlayer的对象,当然能调用start方法了。
其实sp中还重写了 & 和 = 操作符 。
mp的生命周期只在android_media_MediaPlayer_start方法里面有效,方法执行完后就该释放。
这就有问题了,如果mp里面所有内存都释放了,别的地方还有引用,就会出现空指针。如果不释放,别的地方又不引用了,就内存泄露了。
怎么解决这个问题呢?
Android 引入了引用计数,weakref_impl类里面保存引用数目,记录了T被引用的次数。引用次数为0时就释放。但是如过,sp<T1> 和sp<T2>之间相互引用,就相互依赖,没法释放了。这时又引入了强引用和弱引用。
sp wp RefBase T 类之间的关系如下图
用sp<MediaPlayer>分析,计数过程,
return sp<MediaPlayer>(p); 构造时,执行m_ptr->incStrong(this)方法,使MediaPlayer对象的强弱引用都加一,
getMediaPlayer执行完后,会调用匿名对象的析构函数~sp,执行m_ptr->decStrong(this),使MediaPlayer对象的强弱应用都减一。
在android_media_MediaPlayer_start函数里面,对mp进行赋值,使用的是重载的operator=,重载的过程也执行m_ptr->incStrong(this),也使MediaPlayer对象的强弱引用增加1。android_media_MediaPlayer_start函数执行完后,释放mp,会调用mp的析构函数,执行m_ptr->decStrong(this),也使MediaPlayer对象的强弱引用都加一.
Android framework回顾 sp 和 wp sp对象