What to do on TransactionTooLargeException

前端 未结 30 3332
盖世英雄少女心
盖世英雄少女心 2020-11-22 03:08

I got a TransactionTooLargeException. Not reproducible. In the docs it says

The Binder transaction failed because it was too large.

D

相关标签:
30条回答
  • 2020-11-22 03:44

    This is not a definitive answer, but it may shed some light on the causes of a TransactionTooLargeException and help pinpoint the problem.

    Although most answers refer to large amounts of data transferred, I see this exception being thrown incidentally after heavy scrolling and zooming and repeatedly opening an ActionBar spinner menu. The crash happens on tapping the action bar. (this is a custom mapping app)

    The only data being passed around seem to be touches from the "Input Dispatcher" to the app. I think this cannot reasonably amount to anywhere near 1 mb in the "Transaction Buffer".

    My app is running on a quad core 1.6 GHz device and uses 3 threads for heavylifting, keeping one core free for the UI thread. Furthermore, the app uses android:largeHeap, has 10 mb of unused heap left and has 100 mb of room left to grow the heap. So I wouldn't say it is a resource issue.

    The crash is always immediately preceded by these lines:

    W/InputDispatcher( 2271): channel ~ Consumer closed input channel or an error occurred.  events=0x9
    E/InputDispatcher( 2271): channel ~ Channel is unrecoverably broken and will be disposed!
    E/JavaBinder(28182): !!! FAILED BINDER TRANSACTION !!!
    

    Which are not neccesarily printed in that order, but (as far as I checked) happen on the same millisecond.

    And the stack trace itself, for clarity, is the same as in the question:

    E/AndroidRuntime(28182): java.lang.RuntimeException: Adding window failed
    ..
    E/AndroidRuntime(28182): Caused by: android.os.TransactionTooLargeException
    

    Delving into the source code of android one finds these lines:

    frameworks/base/core/jni/android_util_Binder.cpp:

    case FAILED_TRANSACTION:
        ALOGE("!!! FAILED BINDER TRANSACTION !!!");
        // TransactionTooLargeException is a checked exception, only throw from certain methods.
        // FIXME: Transaction too large is the most common reason for FAILED_TRANSACTION
        //        but it is not the only one.  The Binder driver can return BR_FAILED_REPLY
        //        for other reasons also, such as if the transaction is malformed or
        //        refers to an FD that has been closed.  We should change the driver
        //        to enable us to distinguish these cases in the future.
        jniThrowException(env, canThrowRemoteException
                ? "android/os/TransactionTooLargeException"
                        : "java/lang/RuntimeException", NULL);
    

    To me it sounds like I'm possibly hitting this undocumented feature, where the transaction fails for other reasons than a Transaction being TooLarge. They should have named it TransactionTooLargeOrAnotherReasonException.

    At this time I did not solve the issue, but if I find something useful I will update this answer.

    update: it turned out my code leaked some file descriptors, the number of which is maximized in linux (typically 1024), and this seems to have triggered the exception. So it was a resource issue after all. I verified this by opening /dev/zero 1024 times, which resulted in all kinds of weird exceptions in UI related actions, including the exception above, and even some SIGSEGV's. Apparently failure to open a file/socket is not something which is handled/reported very cleanly throughout Android.

    0 讨论(0)
  • 2020-11-22 03:44

    I faced with the same issue when I tried to send bitmap via Intent and at the same time when it happens I folded the application.

    How it described in this article enter link description here it happens when an Activity is in the process of stopping, that means that the Activity was trying to send its saved state Bundles to the system OS for safe keeping for restoration later (after a config change or process death) but that one or more of the Bundles it sent were too large.

    I solved it via hack by overriding onSaveInstanceState in my Activity:

    @Override
    protected void onSaveInstanceState(Bundle outState) {
        // super.onSaveInstanceState(outState);
    }
    

    and comment call super. It is a dirty hack but it is working perfectly. Bitmap was successfully sent without crashes. Hope this will help someone.

    0 讨论(0)
  • 2020-11-22 03:44

    This one line of code in writeToParcel(Parcel dest, int flags) method helped me to get rid of TransactionTooLargeException.

    dest=Parcel.obtain(); 
    

    After this code only i am writing all data to the parcel object i.e dest.writeInt() etc.

    0 讨论(0)
  • 2020-11-22 03:45

    If you need to investigate which Parcel is causing your crash, you should consider trying TooLargeTool.

    (I found this as a comment from @Max Spencer under the accepted answer and it was helpful in my case.)

    0 讨论(0)
  • 2020-11-22 03:45

    One can use:

    android:largeHeap="true"
    

    in Android Manifest under application tag.

    This solved the issue in my case!

    0 讨论(0)
  • 2020-11-22 03:46

    You have clear your old InstanceState from onSaveInstanceState method, and it will work well. I am using FragmentStatePagerAdapter for my viewpager so I keep below Override method into my parent activity for clear InstanceState.

    @Override
    protected void onSaveInstanceState(Bundle InstanceState) {
                 super.onSaveInstanceState(InstanceState);
                 InstanceState.clear();
    }
    

    I found this solution from here android.os.TransactionTooLargeException on Nougat

    0 讨论(0)
提交回复
热议问题