binder对象回收初探

binder回收初探

 

2018-9-27

IPackageDeleteObserver.Stub继承于Binder类,在应用中进行getPackageManager().deletePackage调用的时候,会传递一个Binder的回调对象给PMS(system_server)

       PackageDeleteObserver observer = new PackageDeleteObserver();

       getPackageManager().deletePackage("com.tencent.mm", observer, 0);

这个试验中,我们的每次点击按钮都会创建一个PackageDeleteObserver对象传给PMS,我们尝试多次点击按钮,new很多对象,看看是否会对系统构成攻击。

为了避免PackageDeleteObserver对象的释放,我们甚至采用ArrayList将其引用起来。

 

public class MainActivity extends Activity

implements OnClickListener {

 

       private static final String TAG = "MyService";

       private List<Object> mList = new ArrayList<Object> ();

    public class PackageDeleteObserver extends IPackageDeleteObserver.Stub { 

        public void packageDeleted(boolean succeeded) { 

            Log.i(TAG, "======= UNINSTALL_COMPLETE =========="); 

        }

        public void packageDeleted(String s, int i)

        {

              Log.i(TAG, "=======1 UNINSTALL_COMPLETE ==========");

        } 

    } 

      

       public void onClick(View src)

       {

              Log.i(TAG, "onClick: starting service");

             

              PackageDeleteObserver observer = new PackageDeleteObserver();

              mList.add(observer);

              getPackageManager().deletePackage("com.tencent.mm", observer, 0); 

 

Log.i(TAG, "List.size = " + mList.size());

             Log.i(TAG, "onClick: starting service, end of onClick");

       }

      

不断的点击按钮,同时,观察Local Binders的数量

Unknown:/ $ dumpsys meminfo 7365 | grep Binders

       Local Binders:       26        Proxy Binders:       15

Unknown:/ $ dumpsys meminfo 7365 | grep Binders

       Local Binders:       48        Proxy Binders:       15

Unknown:/ $ dumpsys meminfo 7365 | grep Binders

       Local Binders:       55        Proxy Binders:       15

Unknown:/ $ dumpsys meminfo 7365 | grep Binders

       Local Binders:       13        Proxy Binders:       15

 

结果发现,还是被释放了。

why?

 

打开JavaBBinder中的log来观察期创建和析构,

class JavaBBinder : public BBinder

{

public:

    JavaBBinder(JNIEnv* env, jobject object)

        : mVM(jnienv_to_javavm(env)), mObject(env->NewGlobalRef(object))

    {

        ALOGD("Creating JavaBBinder %p\n", this);

        android_atomic_inc(&gNumLocalRefs);

        incRefsCreated(env);

    }

 

    virtual ~JavaBBinder()

    {

        ALOGD("Destroying JavaBBinder %p\n", this);

        android_atomic_dec(&gNumLocalRefs);

        JNIEnv* env = javavm_to_jnienv(mVM);

        env->DeleteGlobalRef(mObject);

    }

 

结果发现,JavaBBinder对象确实是可以被释放的,

01-01 17:09:01.784  7365  7365 D JavaBinder: Creating JavaBBinder 0x74a3213080

01-01 17:09:13.376  7365  7378 D JavaBinder: Destroying JavaBBinder 0x74a3213080

 

查看Binder.java中的init方法

    private native final void init();

 

其实现在android_util_Binder.cpp中的

static void android_os_Binder_init(JNIEnv* env, jobject obj)

{

    JavaBBinderHolder* jbh = new JavaBBinderHolder();

    if (jbh == NULL) {

        jniThrowException(env, "java/lang/OutOfMemoryError", NULL);

        return;

    }

    ALOGV("Java Binder %p: acquiring first ref on holder %p", obj, jbh);

    jbh->incStrong((void*)android_os_Binder_init);

    env->SetLongField(obj, gBinderOffsets.mObject, (jlong)jbh);

}

 

可以看出,Binder对象关联的是JavaBBinderHolder,而不是JavaBBinder对象。

 

当调用端的BinderProxy对象释放的时候,server端的binder对象在没有被引用的情况下也会被释放。

 

### Telephony Binder 对象的作用与用途 #### 1. Telephony Binder 的定义与作用 Telephony Binder 是 Android 系统中用于实现进程间通信(Inter-Process Communication, IPC)的机制之一。它通过 Binder 框架,使得不同进程之间的对象能够进行方法调用和数据传递[^3]。在 Telephony 领域中,Binder 对象的主要作用是提供一个接口,允许应用层(如 TelephonyManager)与系统服务层(如 Phone 进程中的 PhoneInterfaceManager)进行交互。 Binder 对象的具体实现可以通过 AIDL(Android Interface Definition Language)定义接口,并生成相应的代理类和 Stub 类来完成跨进程调用[^4]。例如,ITelephony 接口就是通过 AIDL 定义的,用于实现应用层与 Phone 进程之间的通信[^3]。 #### 2. Telephony Binder 的具体用途 Telephony Binder 对象主要用于以下场景: - **网络状态查询与设置**:通过 Binder 调用,应用可以查询设备的网络状态、信号强度等信息,或者设置网络模式、搜网等功能[^1]。 - **电话呼叫控制**:应用可以通过 Binder 调用挂断电话、发起呼叫等操作[^3]。 - **短信管理**:发送短信或查询短信状态也可以通过 Telephony Binder 实现。 - **SIM 卡管理**:包括查询 SIM 卡状态、切换 SIM 卡等操作。 这些功能的核心在于 ITelephony 接口的实现。虽然官方建议尽量使用 TelephonyManager 来替代直接调用 ITelephony 接口,但在某些特定场景下,直接使用 ITelephony 可以提供更灵活的功能支持。 #### 3. ITelephony 接口的封装与调用 由于 ITelephony 接口运行在 Phone 进程中,而大多数应用并不运行在该进程中,因此需要对其进行封装以便于调用。封装的方式通常是在 TelephonyManager 中提供一些公开方法,通过这些方法间接调用 ITelephony 接口的功能[^2]。 以下是一个简单的代码示例,展示如何通过 TelephonyManager 调用 ITelephony 接口的方法: ```java public void setValueToModem(int input) { try { // 获取 ITelephony 接口的代理对象 ITelephony telephony = getITelephony(); if (telephony != null) { telephony.setValueToModem(input); // 调用 ITelephony 方法 } } catch (RemoteException ex) { // 处理远程异常 } catch (NullPointerException ex) { // 处理空指针异常 } } ``` #### 4. Binder 机制在 Telephony 中的优势 Binder 机制为 Telephony 提供了以下优势: - **安全性**:通过 Binder,系统可以对跨进程调用进行权限检查,确保只有具有适当权限的应用才能访问敏感功能[^4]。 - **高效性**:Binder 基于 Linux 内核实现,提供了高效的 IPC 机制,减少了跨进程调用的开销。 - **灵活性**:Binder 允许复杂的对象结构在进程间传递,满足了 Telephony 场景下的多样化需求。 #### 5. 示例:手动搜网功能 以手动搜网功能为例,PhoneInterfaceManager 提供了 `requestNetworkScan` 方法,允许应用请求网络扫描并获取可用网络列表[^1]。这一功能的实现依赖于 Binder 机制,通过 ITelephony 接口将请求从应用层传递到 Phone 进程,并最终返回扫描结果。 以下是调用 `requestNetworkScan` 的伪代码示例: ```java // 获取 ITelephony 接口的代理对象 ITelephony telephony = getITelephony(); if (telephony != null) { // 请求网络扫描 List<CellInfo> cellInfos = telephony.requestNetworkScan(); for (CellInfo cellInfo : cellInfos) { // 处理扫描结果 } } ``` ###
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值