跨进程使用ContentProvide出现死循环

本文分析了一个因ContentProvider导致的跨进程死循环调用问题,引发了StackOverflowError异常。问题出现在判断主进程逻辑错误,导致ContentProvider在主进程中仍然尝试跨进程通信。解决方案是避免在ContentProvider中进行主进程判断,从而防止潜在的死循环。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、问题背景

最近遇到了StackOverflowError的异常问题,具体信息如下:

StackTrace=nulljava.lang.StackOverflowError
at java.lang.IntegralToString.convertInt(IntegralToString.java:216)
at java.lang.IntegralToString.appendInt(IntegralToString.java:173)
at java.lang.StringBuilder.append(StringBuilder.java:139)
at com.jb.gokeyboard.theme.b.a(InterprocessDataUtils.java:509)
at com.jb.gokeyboard.ad.j$a.a(GiftBoxAdManager.java:470)
at com.jb.gokeyboard.gostore.GoKeyboardProviderEmoji.a(GoKeyboardProviderEmoji.java:421)
at com.jb.gokeyboard.gostore.GoKeyboardProviderEmoji.query(GoKeyboardProviderEmoji.java:92)
at android.content.ContentProvider.query(ContentProvider.java:857)
at android.content.ContentProvider$Transport.query(ContentProvider.java:200)
at android.content.ContentResolver.query(ContentResolver.java:464)
at android.content.ContentResolver.query(ContentResolver.java:407)
at com.jb.gokeyboard.theme.b.a(InterprocessDataUtils.java:511)
at com.jb.gokeyboard.ad.j$a.a(GiftBoxAdManager.java:470)
at ...

二、问题分析

根据异常信息,我们明显可以知道这是由于死循环调用导致栈溢出的问题。接下来,通过代码进一步分析问题的原因。
class GiftBoxAdManager :

public static class AvailableAdVerify {
        ...
        public static boolean getAdAvaliablity(int virtualID) {
            if (!PackageUtil.isMainProcess(GoKeyboardApplication.getContext())) {
                return InterprocessDataUtils.getAdAvaliability(GoKeyboardApplication.getContext(),
                        virtualID);
            }
            synchronized (sLock) {
                return isAdAvaliabele.get(virtualID, false);
            }
        }
        ...
    }

class InterprocessDataUtils :

public static boolean getAdAvaliability(Context context,int virtualID) {
        ...
        try {
            cursor = context.getApplicationContext().getContentResolver()
                    .query(InterprocessDataUtils.sAdAvaliabilityUri, projection, projection[0], null, null);
            if (cursor != null && cursor.moveToFirst()) {
                value = cursor.getInt(0);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (cursor != null) {
                cursor.close();
            }
        }
        if (value == 1) {
            return true;
        }
        return false;
    }

class GoKeyboardProviderEmoji extends ContentProvider :

private Cursor isAdAvaliable(String[] projection,int virtualID){
        ...
        if (AvailableAdVerify.getAdAvaliablity(virtualID)) {
            objects[0] = 1;
        }else {
            objects[0] = 0;
        }
        MatrixCursor cursor = new MatrixCursor(projection, projection.length);
        cursor.addRow(objects);
        return cursor;
    }

当调用接口AvailableAdVerify.getAdAvaliablity()的时候,会通过PackageUtil.isMainProcess()判断是否为主进程,不是则调用接口InterprocessDataUtils.getAdAvaliability(),再通过ContentProvider跨进程共享数据。这时,由于ContentProvider处于主进程,此时调用接口PackageUtil.isMainProcess()时,正常情况下应该返回true,然而,如果返回false则会出现死循环调用的情况。

三、问题处理

针对该问题,原因是判断是否为主进程的接口出现了错误,然而目前未找出异常情况出现的路径,而从统计上该问题出现的概率也非常小。解决该问题,主要是防止死循环的调用,而我们已经知道ContentProvider一定是处于主进程,因此在ContentProvider中则不需要判断是否为主进程。修改后,如下:
class GiftBoxAdManager :

public static class AvailableAdVerify{
        ...
        public static boolean getAdAvaliablity(int virtualID){
            if (!PackageUtil.isMainProcess(GoKeyboardApplication.getContext())) {
                return InterprocessDataUtils.getAdAvaliability(GoKeyboardApplication.getContext(),virtualID);
            }

            return getAdAvaliablityByMainProcess(virtualID);
        }   

        //主进程中调用
        public static boolean getAdAvaliablityByMainProcess(int virtualID) {
            synchronized (sLock) {
                return isAdAvaliabele.get(virtualID, false);
            }
        }
        ...
    }

class GoKeyboardProviderEmoji extends ContentProvider :

private Cursor isAdAvaliable(String[] projection,int virtualID){
        ...
        if (AvailableAdVerify.getAdAvaliablityByMainProcess(virtualID)) {
            objects[0] = 1;
        }else {
            objects[0] = 0;
        }

        MatrixCursor cursor = new MatrixCursor(projection, projection.length);
        cursor.addRow(objects);
        return cursor;
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值