Java lang runtimeexception android os transactiontoolargeexception data parcel size

android.os.TransactionTooLargeException #15429

Comments

kelset commented Aug 9, 2017

Is this a bug report?

Have you read the Contributing Guidelines?

Environment

  1. react-native -v : react-native-cli: 2.0.1, react-native: 0.46.4
  2. node -v : v8.2.1
  3. npm -v : v5.3.0
  4. yarn —version : 0.27.5
  • Target Platform: iOS, Android
  • Development Operating System: macOS
  • Build tools: XCode & Android Studio

The issue is related to Android 7.

Steps to Reproduce

Don’t really know.

Expected Behavior

Actual Behavior

Fabric reports that a few users, all running Android 7 devices, experience this crash (1 time each user):

And I have no clue what this issue is caused by; I think it’s related to the new react-native version, since the crash is only present in the new version of our app ( the previous version was running 0.45). Another change between this version and the previous is that we upped Android’s build to use compileSdkVersion 25, buildToolsVersion ‘25.0.2’ .

I couldn’t find any report of this issue so I’m opening this issue.

Reproducible Demo

(don’t know what causes the issue)

The text was updated successfully, but these errors were encountered:

hey99xx commented Aug 11, 2017

Another change between this version and the previous is that we upped Android’s build to use compileSdkVersion 25, buildToolsVersion ‘25.0.2’.

It is likely this point that causes the crash, so it’s not really about react-native. On Android Nougat, this is one of the new behaviors https://developer.android.com/about/versions/nougat/android-7.0-changes.html#other

Many platform APIs have now started checking for large payloads being sent across Binder transactions, and the system now rethrows TransactionTooLargeExceptions as RuntimeExceptions, instead of silently logging or suppressing them. One common example is storing too much data in Activity.onSaveInstanceState(), which causes ActivityThread.StopInfo to throw a RuntimeException when your app targets Android 7.0.

stephenfromrobin commented Aug 15, 2017

Any ideas on what can be done about this?

@hey99xx -maybe you have a suggestion?

kelset commented Aug 21, 2017

It is likely this point that causes the crash, so it’s not really about react-native.

I agree that it is something related to Nougat, but it also means that react native is not «ready» to handle Android 7.0 properly — reason why I decided to open the issue.

My best guess is that some internals on current react native version are sending large payloads across Binder, so by reporting the issue maybe some cool dev can understand and fix this issue OR provide a workaround 😉

jgale commented Aug 22, 2017

Another change between this version and the previous is that we upped Android’s build to use compileSdkVersion 25, buildToolsVersion ‘25.0.2’.

It is likely this point that causes the crash, so it’s not really about react-native. On Android Nougat, this is one of the new behaviors https://developer.android.com/about/versions/nougat/android-7.0-changes.html#other

One thing I wanted to clarify here – according to this extremely helpful post from a Google employee, Picking your compileSdkVersion, minSdkVersion, and targetSdkVersion:

It should be emphasized that changing your compileSdkVersion does not change runtime behavior.

Correct me if I’m wrong, but changing compileSdkVersion to 25 should not cause a crash. However, if the targetSdkVersion was also updated to 25, then you might see this change in behavior. Did you update the targetSdkVersion as well @kelset?

If so, this probably doesn’t help you that much since it’s still recommended to try and update to targetSdVersion to the latest and test under that platform. If React Native doesn’t work well with a with a targetSdVersion of Nougat, that’s still a problem that needs to be solved.

Читайте также:  Как восстановить андроид до заводских настроек через рекавери

(I ask because I’m looking to update compileSdkVersion in my RN app but wasn’t brave enough to update targetSdkVersion yet.)

Источник

Что делать с TransactionTooLargeException

Я получил ошибочную информацию о приложении TransactionTooLargeException. Не воспроизводимо и никогда не было. В документах говорится:

Не удалось выполнить транзакцию Binder, потому что она слишком велика.

Во время вызова удаленной процедуры аргументы и возвращаемое значение вызова передаются как объекты Parcel, хранящиеся в буфере транзакции Binder. Если аргументы или возвращаемое значение слишком велики для размещения в буфере транзакций, тогда вызов завершится с ошибкой и будет выведено TransactionTooLargeException.

Есть два возможных результата, когда удаленный вызов процедуры вызывает TransactionTooLargeException. Либо клиент не смог отправить свой запрос на услугу (скорее всего, если аргументы были слишком большими, чтобы вписаться в буфер транзакции), либо служба не смогла отправить свой ответ клиенту (скорее всего, если возвращаемое значение было Слишком большой, чтобы вписаться в буфер транзакции).

Итак, хорошо, где-то я передаю или получаю аргументы, которые превышают некоторый неизвестный предел. Но где?

Стек-стек не показывает ничего из моих файлов:

Кажется, это связано с представлениями, потому что все строки Window / View? Как это связано с удаленным вызовом процедуры? Как я могу найти причину этой ошибки?

В приложении я использую только Webservices, я не пользуюсь классом Service, являются ли Webservices «удаленные вызовы процедур» или что еще может быть …?

PS Может быть, это важно: версия для Android: 4.0.3, Устройство: HTC One X

Я столкнулся с этой проблемой, и я обнаружил, что при обмене огромным количеством данных между сервисом и приложением (это включает в себя передачу большого количества миниатюр). Фактически размер данных был около 500 КБ, а размер буфера транзакций IPC установлен равным 1024 КБ. Я не уверен, почему он превысил буфер транзакций.

Это также может произойти, когда вы передаете много данных с помощью дополнительных намерений

Когда вы получите это исключение в своем приложении, проанализируйте свой код.

  1. Вы обмениваете много данных между вашими услугами и приложением?
  2. Используя намерения обмениваться огромными данными (например, пользователь выбирает огромное количество файлов из общей папки общего доступа к галерее, URI выбранных файлов будут переданы с использованием намерений)
  3. Получение растровых файлов из службы
  4. Ожидая андроида, чтобы откликнуться на огромные данные (например, getInstalledApplications (), когда пользователь установил много приложений)
  5. Используя applyBatch () с множеством ожидающих операций

Как обращаться, когда вы получаете это исключение

Если возможно, разделите большую операцию на небольшие куски, например, вместо вызова applyBatch () с 1000 операций, вызовите его по 100 каждый.

Не обменивайте огромные данные (> 1 МБ) между сервисами и приложениями

Я не знаю, как это сделать, но, не запрашивайте андроид, который может вернуть огромные данные 🙂

Это не окончательный ответ, но он может пролить свет на причины TransactionTooLargeException и помочь определить проблему.

Хотя большинство ответов относятся к большому количеству переданных данных, я вижу, что это исключение выбрасывается случайно после интенсивной прокрутки и масштабирования и неоднократного открытия меню Spinner ActionBar. Авария происходит при нажатии на панель действий. (Это настраиваемое приложение для сопоставления)

Единственные передаваемые данные, похоже, касаются «Input Dispatcher» в приложении. Я думаю, что это не может разумно равняться примерно 1 мб в «Буфере транзакций».

Мое приложение работает на четырехъядерном процессоре с тактовой частотой 1,6 ГГц и использует 3 потока для тяжелой атлетики, оставляя одно ядро ​​свободным для потока пользовательского интерфейса. Кроме того, приложение использует андроид: largeHeap, имеет 10 мб неиспользуемой кучи слева и имеет 100 мб комнаты, чтобы увеличить кучу. Поэтому я бы не сказал, что это проблема с ресурсами.

Катастрофу всегда предшествуют следующие строки:

Которые не обязательно печатаются в этом порядке, но (насколько я проверял) происходят на той же миллисекунде.

И сама трассировка стека, для ясности, такая же, как и в вопросе:

Вводя исходный код андроида, вы обнаружите следующие строки:

рамки / база / ядро ​​/ JNI / android_util_Binder.cpp:

Читайте также:  Андроид точка ком свитч

Для меня это звучит так, будто я, возможно, ударяю эту недокументированную функцию, где транзакция не выполняется по другим причинам, чем транзакция, являющаяся TooLarge. Они должны были назвать это TransactionTooLargeOrAnotherReasonException .

В это время я не решил проблему, но если я найду что-то полезное, я обновлю этот ответ.

Update: выяснилось, что мой код просочился в некоторые файловые дескрипторы, число которых максимизировано в linux (обычно 1024), и это, похоже, вызвало исключение. Так что это была проблема с ресурсами. Я проверил это, открыв /dev/zero 1024 раза, что привело к появлению всех видов странных исключений в действиях, связанных с пользовательским интерфейсом, включая исключение выше и даже некоторые SIGSEGV. По-видимому, отказ открыть файл / сокет – это не то, что обрабатывается / сообщается очень чисто на Android.

Не существует одной конкретной причины этой проблемы. Для меня в моем классе Fragment я делал это:

У меня тоже есть это исключение на Samsung S3. Я подозреваю 2 причины,

  1. У вас есть растровые изображения, которые загружают и занимают слишком много памяти, используют сокращение
  2. У вас есть некоторые недостатки в папках drawable-_dpi, android ищет их в drawable и изменяет их размеры, заставляя ваш setContentView внезапно прыгать и использовать много памяти.

Используйте DDMS и смотрите на свою кучу, когда играете в свое приложение, что даст вам некоторое указание на то, что setcontentview создает проблему.

Я скопировал все чертежи во всех папках, чтобы избавиться от проблемы 2.

Через несколько дней я расскажу, что я нахожу.

TransactionTooLargeException преследует нас примерно 4 месяца, и мы, наконец, решили проблему!

Что происходит, мы использовали FragmentStatePagerAdapter в ViewPager. Пользователь будет просматривать страницы и создавать более 100 фрагментов (это приложение для чтения).

Хотя мы правильно управляем фрагментами в destroyItem (), в реализации Androids для FragmentStatePagerAdapter появляется ошибка, в которой содержится ссылка на следующий список:

И когда FragmentStatePagerAdapter Android попытается сохранить состояние, он вызовет функцию

Как вы можете видеть, даже если вы правильно управляете фрагментами в подклассе FragmentStatePagerAdapter, базовый класс по-прежнему будет хранить Fragment.SavedState для каждого отдельного фрагмента, когда-либо созданного. TransactionTooLargeException произойдет, когда этот массив будет сброшен в parcelableArray, и OS не понравится более 100 элементов.

Поэтому исправление для нас состояло в том, чтобы переопределить метод saveState () и не хранить ничего для «состояний».

Для тех, кто горько разочарован в поисках ответа о том, почему появляется TransactionTooLargeException, попробуйте проверить, что вы сохраняете в состоянии экземпляра.

В compile / targetSdkVersion = 23 у нас есть только внутреннее предупреждение о большом размере сохраненного состояния, но ничто не разбивается:

Но при компиляции / targetSdkVersion = 24 и выше у нас возникает реальная авария RuntimeException в этом случае:

Что делать?

Сохраните данные в локальной базе данных и сохраните только идентификатор в состоянии экземпляра, который вы можете использовать для извлечения этих данных.

Важно понимать, что буфер транзакций ограничен 1 МБ, независимо от возможностей устройства или приложения. Этот буфер используется с каждым вызовом API, который вы делаете, и разделяется между всеми транзакциями, выполняемыми в настоящее время в приложении.

Я считаю, что он также содержит некоторые конкретные объекты, такие как посылки и т. Д. (Parcel.obtain()) , поэтому важно всегда сопоставлять каждый obtain() с recycle() .

Эта ошибка может легко произойти при вызовах API, возвращающих много данных, даже если возвращаемые данные меньше 1 МБ (если другие транзакции все еще работают).

Например, вызов PackageManager.getInstalledApplication() возвращает список всех установленных приложений. Добавление определенных флагов позволяет получить много дополнительных данных. Это может привести к сбою, поэтому рекомендуется не извлекать лишние данные и извлекать их для каждого приложения.

Однако вызов может по-прежнему терпеть неудачу, поэтому важно окружить его уловкой и, если необходимо, повторить попытку.

Насколько я знаю, нет никакой проблемы с такой проблемой, кроме повторной попытки и получения как можно меньше информации.

Поэтому для нас это было то, что мы пытались отправить слишком большой объект через наш интерфейс AIDL в удаленную службу. Размер транзакции не может превышать 1 МБ. Запрос разбивается на отдельные куски 512 КБ и отправляется по одному через интерфейс. Жестокое решение, которое я знаю, но эй – его Android 🙁

Читайте также:  What is fitssystemwindows android

Другая возможная причина:

У меня была активность, которая начиналась в onResume() ! Это приводит к тонне транзакций и приводит к тому, что телефон (Galaxy S2) полностью замораживает (без ANR или что-то еще), а затем к жесткому сбросу, что является своего рода огромной ошибкой.

Было бы интересно посмотреть, что происходит на других телефонах с этим кодом:

Недавно я также столкнулся с интересным случаем, работая с поставщиком контактов Android.

Мне нужно было загружать фотографии контактов из базы данных внутренних контактов, и в соответствии с архитектурой системы все эти данные доставляются по запросам в «Поставщик контактов».

Поскольку это работает как отдельное приложение – все виды передачи данных выполняются с использованием механизма Binder, и поэтому сюда входит Binder buffer.

Моя основная ошибка заключалась в том, что я не закрыл Cursor с данными blob, полученными от поставщика контактов, так что память, выделенная для провайдера, увеличилась, и это надуло буфера Binder, пока я не получил тонны . FAILED BINDER TRANSACTION. Сообщений на моем выходе LogCat.

Поэтому основная идея заключается в том, что когда вы работаете с внешними поставщиками контента и получаете от них Cursor , всегда закрывайте его, когда вы заканчиваете работать с ними.

В моем случае я получаю TransactionTooLargeException как вторичный сбой после того, как родная библиотека разбилась с SIGSEGV. Сбой родной библиотеки не сообщается, поэтому я получаю TransactionTooLargeException.

Убедитесь, что вы не помещаете данные объекта Intent большого размера. В моем случае я добавлял размер String 500k, а затем запускал другое действие. Это исключение всегда не срабатывало. Я избегал обмена данными между действиями с использованием статических переменных действий – вам не нужно отправлять их в Intent, а затем извлекать из него.

Что у меня было:

Я нашел основную причину этого (мы получили как «добавление окна не удалось», так и утечку дескриптора файла, как говорит mvds).

В BitmapFactory.decodeFileDescriptor() для Android 4.4 есть ошибка. Это происходит только тогда, когда inPurgeable и inInputShareable из BitmapOptions имеют значение true. Это приводит к тому, что многие проблемы во многих местах взаимодействуют с файлами. https://code.google.com/p/android/issues/detail?id=65638

Обратите внимание, что этот метод также вызывается из MediaStore.Images.Thumbnails.getThumbnail() .

Эта проблема затронута Universal Image Loader. Пикассо и Глейд, похоже, не затронуты.

Я получил это в своем syncadapter при попытке bulkInsert большой ContentValues ​​[]. Я решил исправить это следующим образом:

Когда я имею дело с WebViewin моего приложения, это случается. Я думаю, что это связано с ресурсами addView и UI. В моем приложении я добавляю код в WebViewActivity, как показано ниже, он работает нормально:

Решением было бы приложение написать ArrayList (или любой объект, вызывающий проблему) в файловую систему, затем передать ссылку на этот файл (например, имя файла / путь) через Intent на IntentService, а затем позволить IntentService Получить содержимое файла и преобразовать его обратно в ArrayList.

Когда IntentService сделал с файлом, он должен либо удалить его, либо передать инструкцию обратно в приложение через локальную широковещательную рассылку, чтобы удалить созданный файл (передав обратно ту же ссылку на файл, которая была ему предоставлена).

Для получения дополнительной информации см. Мой ответ на эту связанную проблему .

Как Intents, Content Providers, Messenger, все системные службы, такие как Telephone, Vibrator и т. Д. Используют провайдера инфраструктуры IPC по Binder. Кроме того, в этой функции задействованы обратные вызовы жизненного цикла активности.

1 МБ – это общий предел для всех транзакций связующего, выполненных в системе в определенный момент.

В случае, если при отправке намерения происходит много транзакций, он может выйти из строя, даже если дополнительные данные невелики. http://codetheory.in/an-overview-of-android-binder-framework/

Я столкнулся с той же проблемой и нашел решение. Я передавал много данных с помощью дополнительных утилит:

Вместо intent.putExtra(String name, String value); , Просто используйте

GetValue – статическая переменная, объявленная в SecondActivity.

Источник

Оцените статью