java.lang.RuntimeException: android.os.TransactionTooLargeException: data parcel size 520536 bytes

最近项目测试的时候遇到一个隐藏的bug,之前一直测试一直没有测出来,而且运行的时候不会报错,下面是bug描述:

    

11-16 17:07:51.301 12598-12598/com.hx.socialapp E/JavaBinder: !!! FAILED BINDER TRANSACTION !!!  (parcel size = 520536)
11-16 17:07:51.326 12598-12598/com.hx.socialapp E/RongLog: [ RongExceptionHandler ] uncaughtException
                                                           java.lang.RuntimeException: android.os.TransactionTooLargeException: data parcel size 520536 bytes
                                                               at android.app.ActivityThread$StopInfo.run(ActivityThread.java:4050)
                                                               at android.os.Handler.handleCallback(Handler.java:836)
                                                               at android.os.Handler.dispatchMessage(Handler.java:103)
                                                               at android.os.Looper.loop(Looper.java:203)
                                                               at android.app.ActivityThread.main(ActivityThread.java:6436)
                                                               at java.lang.reflect.Method.invoke(Native Method)
                                                               at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1113)
                                                               at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:974)
                                                            Caused by: android.os.TransactionTooLargeException: data parcel size 520536 bytes
                                                               at android.os.BinderProxy.transactNative(Native Method)
                                                               at android.os.BinderProxy.transact(Binder.java:626)
                                                               at android.app.ActivityManagerProxy.activityStopped(ActivityManagerNative.java:3908)
                                                               at android.app.ActivityThread$StopInfo.run(ActivityThread.java:4042)
                                                               at android.os.Handler.handleCallback(Handler.java:836) 
                                                               at android.os.Handler.dispatchMessage(Handler.java:103) 
                                                               at android.os.Looper.loop(Looper.java:203) 
                                                               at android.app.ActivityThread.main(ActivityThread.java:6436) 
                                                               at java.lang.reflect.Method.invoke(Native Method) 
                                                               at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1113) 
                                                               at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:974) 
 刚开始看这个异常, 是在跳转页面的发现的,因为看不出是哪个activity,以为是跳转到另外一个界面的activity,.找了半天都没有解决.

后来检查了一下代码,发现都是代码: 传递的数据都是很小的,,根本不够512KB, 既然不会报这个异常,为啥他报这个异常呢?

  后来自己重新仔仔细细检查了一下.原来是把一个String 当成bean给传递了,传递给下面的fragment又没有接,造成了,错误代码如下:

 Bundle b = new Bundle();
            ShopTypeCommodityFragment fragment = new ShopTypeCommodityFragment();
            b.putInt("shopindex", i);
            b.putSerializable("shopoffid", mShopList.get(i).getId());
            b.putSerializable("shopoffline", (Serializable) mShopList);
            fragment.setArguments(b);
           /* Fragment fragment = ShopTypeCommodityFragment.getInstance(b);
            //mFragmentList.add(fragment);*/
            Log.i("onCreateView", "onCreateViewmShopIndexyyy " + mShopList.get(i).getId());
            mFragmentList.add(fragment);

 正确的代码应该是:

for (int i = 0; i < mShopList.size(); i++) {
            Bundle b = new Bundle();
            ShopTypeCommodityFragment fragment = new ShopTypeCommodityFragment();
            b.putInt("shopindex", i);
            b.putSerializable("shopoffline", (Serializable) mShopList);
            fragment.setArguments(b);
           /* Fragment fragment = ShopTypeCommodityFragment.getInstance(b);
            //mFragmentList.add(fragment);*/
            Log.i("onCreateView", "onCreateViewmShopIndexyyy " + mShopList.get(i).getId());
            mFragmentList.add(fragment);
        }
  自己写代码写漏了,把String 给序列化传递.导致出现这个异常.


   下面的部分还是网站总结比较好的一篇博客,贴到下面供大家参考:

这个问题没找到官方说明,针对网上的各种答案,自己实际测试了一下。

0x01结论

1.1传512K以下的数据的数据可以正常传递。

1.2传512K~1024K的数据会出错,闪退。

1.3传1024K以上的数据会报错:TransactionTooLargeException。

1.4考虑到Intent还包括要启动的Activity等信息,实际可以传的数据略小于512K

0x02准备工作

2.1怎么查看占用内存大小

见参考文献1、2。

2.2构建要传的数据

①我们构建一个1K的字符串; 
②再构建ArrayList的字符串列表; 
③用Intent.putStringArrayListExtra传递 
我们知道1个char占2个字节,那么构建一个512的字符串就刚好1K了。 
实测的时候发现512占了1040,于是减掉8个,取504个。

        int size=504;
        mStringBuilder=new StringBuilder(size);
        for(int i=0;i<size;i++){
            mStringBuilder.append("a");
        }
        //这个mString占1024bytes
        mString=mStringBuilder.toString();
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

2.3循环测试

public void openActivity() {
        try {
            mIntent = new Intent(this, TestActivity2.class);
            //这里要注意的,只有每次都add一个新的字符串,mStringList的大小才会线性变大,否则,指向的是同一个地址
            //但是,即使指向同一个地址,在put的时候也是会出错的,原因,就是因为put要放入每一个值吧。
            mStrngList.add(mStringBuilder.toString());
            mIntent.putStringArrayListExtra("string_list", mStrngList);
            Log.d("test", "put size:" + mStrngList.size());
            startActivityForResult(mIntent, REQUEST_CODE_TEST);
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    //在这里在调用打开,就循环了
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if(resultCode==RESULT_OK && requestCode==REQUEST_CODE_TEST && mContinue){
            openActivity();
        }
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

2.4分析第509的时候闪退

当mArrayList的size是509的时候,就闪退了。 
有以下两张图。 
java.lang.RuntimeException: android.os.TransactionTooLargeException: data parcel size 520536 bytes_第1张图片 
java.lang.RuntimeException: android.os.TransactionTooLargeException: data parcel size 520536 bytes_第2张图片 
可以看到508的时候 
522936/1024=510.68 
509的时候 
523960/1024=511.68 
虽然还没有到512,但我还是得出512的结论,原因是Intent的其他内容也要占内存,所以诱发闪退的原因应该是512.

2.5循环查找TransactionTooLargeException下限

改下测试代码

public void openActivity() {
        try {
            mIntent = new Intent(this, TestActivity2.class);
            mStrngList.remove(0);
            Log.d("test", "try put size:" + mStrngList.size());
            mIntent.putStringArrayListExtra("string_list", mStrngList);
            startActivityForResult(mIntent, REQUEST_CODE_TEST);
            Log.d("test", "put success:" + mStrngList.size());
        }catch (Exception e){
            e.printStackTrace();
            openActivity();
        }
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

2.6分析1018下限

1018的时候闪退,1019时捕获异常。

E/JavaBinder: !!! FAILED BINDER TRANSACTION !!!  (parcel size = 1039780)
Caused by: android.os.TransactionTooLargeException: data parcel size 1039780 bytes
  • 1
  • 2
  • 3

这个官方是有说明的,最在1M(见参考文献3), 
上面的1039780/1024=1015.41,哈哈,不要在乎这些细节。 
看下面2张图 
1018 
1019 
1046536/1024=1022.01 
1047560/1024=1023.01

    
     

        

你可能感兴趣的:(安卓Bug)