333 votes

Que faire sur TransactionTooLargeException

Je suis dans l'erreur, suivi d'une application TransactionTooLargeException. Non reproductibles et n'a jamais eu avant. Dans la doc il est dit

Le Liant de la transaction a échoué parce qu'elle était trop grande.

Lors d'un appel de procédure à distance, les arguments et la valeur de retour de l'appel sont transférés en tant que Colis objets stockés dans le Classeur de transaction de la mémoire tampon. Si les arguments ou la valeur de retour sont trop volumineux pour tenir dans la mémoire tampon de transaction, l'appel échouera et TransactionTooLargeException sera levée.

...

Il y a deux résultats possibles lors d'un appel de procédure distante jette TransactionTooLargeException. Soit le client n'a pas pu envoyer sa demande au service (le plus probable si les arguments étaient trop volumineux pour tenir dans la mémoire tampon de transaction), ou le service n'a pas pu envoyer sa réponse au client (le plus probable si la valeur de retour est trop grand pour tenir dans la mémoire tampon de transaction).

...

Donc, ok, je suis de passage ou de recevoir des arguments qui dépassent une certaine inconnue limite. Mais où?

La stacktrace ne pas montrer quoi que ce soit à partir de mes fichiers:

java.lang.RuntimeException: Adding window failed
at android.view.ViewRootImpl.setView(ViewRootImpl.java:548)
at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:406)
at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:320)
at android.view.WindowManagerImpl$CompatModeWrapper.addView(WindowManagerImpl.java:152)
at android.view.Window$LocalWindowManager.addView(Window.java:557)
at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:2897)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2245)
at android.app.ActivityThread.access$600(ActivityThread.java:139)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1262)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:4977)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551)
at dalvik.system.NativeStart.main(Native Method)
Caused by: android.os.TransactionTooLargeException
at android.os.BinderProxy.transact(Native Method)
at android.view.IWindowSession$Stub$Proxy.add(IWindowSession.java:569)
at android.view.ViewRootImpl.setView(ViewRootImpl.java:538)
... 16 more
android.os.TransactionTooLargeException
at android.os.BinderProxy.transact(Native Method)
at android.view.IWindowSession$Stub$Proxy.add(IWindowSession.java:569)
at android.view.ViewRootImpl.setView(ViewRootImpl.java:538)
at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:406)
at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:320)
at android.view.WindowManagerImpl$CompatModeWrapper.addView(WindowManagerImpl.java:152)
at android.view.Window$LocalWindowManager.addView(Window.java:557)
at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:2897)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2245)
at android.app.ActivityThread.access$600(ActivityThread.java:139)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1262)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:4977)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551)
at dalvik.system.NativeStart.main(Native Method)

Il semble être lié avec des points de vue, parce que toutes les Fenêtre / Afficher les lignes? Comment est-ce lié à l'appel de procédure à distance? Comment puis-je en chercher la raison de cette erreur?

Dans l'application que je suis en utilisant uniquement des Webservices, je ne suis pas à l'aide de la catégorie de Service, sont les Webservices les "appels de procédure distante" ou quoi d'autre pourrait être...?

Merci à l'avance...

P. S. c'est Peut-être important: version Android: 4.0.3, l'Appareil: HTC One X

198voto

Durairaj Packirisamy Points 1755

J'ai rencontré ce problème, et j'ai constaté que quand il y a une immense quantité de données se échangées entre un service et une application(il s'agit de transférer beaucoup de vignettes). En fait la taille des données a été autour de 500ko, et l'IPC de la transaction taille de la mémoire tampon est fixée à 1024 kb. Je ne suis pas sûr de savoir pourquoi il a dépassé le tampon de transaction.

Ceci peut également se produire lorsque vous passez beaucoup de données grâce à l'intention des extras

Lorsque vous obtenez cette exception dans votre demande, veuillez analyser votre code.

  1. Êtes-vous en échange de beaucoup de données entre vos services et de l'application?
  2. En utilisant les intentions de partager des données énormes, (par exemple, l'utilisateur sélectionne grand nombre de fichiers de la galerie partager appuyez sur partager, l'Uri des fichiers sélectionnés seront transférés à l'aide d'intentions)
  3. réception des fichiers bitmap de service
  4. d'attente pour android afin de répondre de retour avec de grandes quantités de données (par exemple, getInstalledApplications() lorsque l'utilisateur a installé beaucoup d'applications)
  5. à l'aide de applyBatch() avec beaucoup d'opérations en attente

Comment gérer lorsque vous obtenez cette exception

Si possible, diviser la grosse opération en petits morceaux, par exemple, au lieu d'appeler applyBatch() avec 1000 opérations, appeler avec des 100 chaque.

Ne pas échanger de données énorme (>1MO) entre les services et l'application

Je ne sais pas comment le faire, mais, de Ne pas interroger android, qui peut retourner des données énorme :-)

50voto

mvds Points 26475

Ce n'est pas une réponse définitive, mais il peut jeter quelque lumière sur les causes de l' TransactionTooLargeException et vous aider à cerner le problème.

Bien que la plupart des réponses se réfèrent à de grandes quantités de données transférées, je vois cette exception levée d'ailleurs après lourds de défilement et de zoom et à plusieurs reprises l'ouverture d'une ActionBar spinner menu. L'accident se produit sur tapant sur la barre d'action. (c'est une coutume de la cartographie app)

Les seules données étant passé autour semblent être touche à partir de l'Entrée "Dispatcher" de l'application. Je pense que cela ne peut pas raisonnablement montant à n'importe où près de 1 mo dans le "Tampon de Transaction".

Mon application est en cours d'exécution sur un processeur quad core 1.6 GHz appareil et utilise 3 fils pour heavylifting, en gardant un cœur pour le thread d'INTERFACE utilisateur. En outre, l'application utilise android:largeHeap, a 10 mo de la partie inutilisée des tas de gauche et a 100 mo de place à gauche pour pousser le tas. Donc, je ne dirais pas que c'est une question de ressources.

L'accident est toujours précédée par ces lignes:

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 !!!

Qui ne sont pas nécessairement imprimées dans l'ordre, mais (aussi loin que j'ai vérifié) arrivent à la même milliseconde.

Et la trace de la pile elle-même, pour plus de clarté, est la même que dans la question:

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

Fouiller dans le code source d'android, on trouve ces lignes:

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);

Pour moi, ça sonne comme si je suis peut-être de frapper cette fonctionnalité non documentée, où la transaction échoue pour des raisons autres qu'une Opération TooLarge. Ils devraient avoir nommé TransactionTooLargeOrAnotherReasonException.

En ce moment je n'ai pas de résoudre le problème, mais si je trouve quelque chose d'utile, je mettrai à jour cette réponse.

mise à jour: il s'est avéré que mon code fuite de certains descripteurs de fichiers, dont le nombre est maximisée sous linux (généralement 1024), et il semble avoir déclenché l'exception. C'était donc une question de ressources, après tout. J'ai vérifié en ouvrant /dev/zero 1024 fois, ce qui a entraîné toutes sortes de bizarre exceptions dans l'INTERFACE utilisateur des actions connexes, y compris l'exception ci-dessus, et même certains SIGSEGV. Apparemment, l'absence d'ouverture d'un fichier/socket n'est pas quelque chose qui est traitées/déclarées très proprement tout au long de Android.

12voto

3c71 Points 803

Il est important de comprendre que le tampon de transaction est limitée à 1 mo, quel que soit le périphérique des capacités ou de l'application. Ce tampon est utilisé avec tous les appels d'API que vous faites et est partagée entre toutes les transactions d'une application est en cours d'exécution.

Je crois qu'il détient également un objet spécifique comme colis et tel (Colis.obtenir()), il est donc important de toujours correspondre à tous les obtenir() avec un recyclage().

Cette erreur peut facilement se passe sur les appels d'API retour d'un grand nombre de données, même si les données renvoyées sont moins de 1 mo (si d'autres opérations sont toujours en cours d'exécution).

Par exemple, le PackageManager.getInstalledApplication() qui renvoie une liste de toutes les applications installées. Ajouter des indicateurs spécifiques permettant de récupérer beaucoup de données supplémentaires. Cela est susceptible d'échouer, il est donc recommandé de ne pas récupérer toutes les données supplémentaires. et de récupérer ceux sur une base par application.

Toutefois, l'appel peut encore échouer, il est donc important pour l'entourer avec une prise et d'être en mesure de réessayer si nécessaire.

Autant que je sache, il n'y a pas de travail autour de cette question à l'exception de réessayer et assurez-vous de récupérer des informations aussi peu que possible.

9voto

Siddharth Points 3828

Moi aussi j'ai eu cette exception sur un Samsung S3. Je soupçonne que 2 causes profondes,

  1. vous avez des bitmaps de charge et de prendre trop de mémoire, utiliser la réduction des effectifs
  2. Vous avez quelques un drawable manquant dans le drawable-_dpi dossiers, android cherche dans drawable, et redimensionne, ce qui rend votre setContentView soudainement sauter et utiliser beaucoup de mémoire.

Utilisation DDMS et de regarder votre tas que vous jouez votre app, qui vous donnera quelques indications sur ce qui setcontentview est la création de la question.

J'ai copié tous les un drawable dans tous les dossiers pour se débarrasser du problème 2.

Je vais rendre compte dans quelques jours, ce que je trouve.

3voto

Alex Bonel Points 535

Récemment, j'ai aussi rencontré avec un cas intéressant, tout en travaillant avec Android Contacts Fournisseur.

J'avais besoin de charger les photos des contacts de contacts internes de la base de données et en fonction de l'architecture du système l'ensemble de ces données sont dispensés par des requêtes à des Contacts Fournisseur.

Comme il fonctionne comme une application séparée - tous les types de transfert de données sont effectuées à l'aide de Liant mécanisme et ainsi de Liant tampon entre ici en jeu.

Ma principale erreur a été que je n'ai pas fermé l' Cursor avec les données blob obtenu à partir des Contacts Fournisseur, de sorte que la mémoire allouée pour le fournisseur augmenté, ce qui a gonflé le Liant de la mémoire tampon jusqu'à ce que j'ai reçu des tonnes de !!!FAILED BINDER TRANSACTION!!! messages dans mon LogCat de sortie.

Donc, l'idée principale est que lorsque vous travaillez avec des Fournisseurs de Contenu externes et a obtenu Cursors d'eux, toujours fermer lorsque vous avez fini de travailler avec eux.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X