286

取得しましたTransactionTooLargeException。再現性がありません。ドキュメントではそれは言う

バインダートランザクションが大きすぎるために失敗しました。

リモートプロシージャコール中に、引数と呼び出しの戻り値は、Binderトランザクションバッファに格納されているParcelオブジェクトとして転送されます。引数または戻り値が大きすぎてトランザクションバッファに収まらない場合、呼び出しは失敗し、TransactionTooLargeExceptionがスローされます。

..。

リモートプロシージャコールがTransactionTooLargeExceptionをスローすると、2つの結果が考えられます。クライアントが要求をサービスに送信できなかったか(引数が大きすぎてトランザクションバッファーに収まらない場合)、またはサービスが応答をクライアントに返送できなかった(戻り値が大きすぎてトランザクションバッファに収まりません)。

..。

だからどこかで私はいくつかの未知の限界を超える引数を渡したり受け取ったりしています。どこ?

スタックトレースには有用なものは何も表示されません。

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)

ビューと関係があるようですか?これはリモートプロシージャコールとどのように関連していますか?

おそらく重要:Androidバージョン:4.0.3、デバイス:HTC One X

4

42 に答える 42

186

私はこの問題に遭遇し、サービスとアプリケーションの間で大量のデータが交換されている場合に発見しました (これには大量のサムネイルの転送が含まれます)。実際のデータ サイズは 500kb 程度で、IPC トランザクション バッファ サイズは 1024KB に設定されています。トランザクション バッファを超えた理由はわかりません。

これは、インテントエクストラを介して大量のデータを渡すときにも発生する可能性があります

アプリケーションでこの例外が発生した場合は、コードを分析してください。

  1. サービスとアプリケーションの間で大量のデータを交換していますか?
  2. インテントを使用して膨大なデータを共有する (たとえば、ユーザーがギャラリー シェア プレス シェアから膨大な数のファイルを選択すると、選択したファイルの URI がインテントを使用して転送されます)
  3. サービスからビットマップ ファイルを受け取る
  4. Android が膨大なデータで応答するのを待っています (たとえば、ユーザーが多くのアプリケーションをインストールした場合の getInstalledApplications())。
  5. 保留中の多くの操作で applyBatch() を使用する

この例外が発生した場合の処理​​方法

可能であれば、大きな操作を小さなチャンクに分割します。たとえば、applyBatch() を 1000 の操作で呼び出すのではなく、それぞれ 100 で呼び出します。

サービスとアプリケーションの間で巨大なデータ (>1MB) を交換しない

これを行う方法はわかりませんが、膨大なデータを返す可能性のあるアンドロイドにクエリを実行しないでください:-)

于 2012-10-09T22:10:26.073 に答える
46

これは決定的な答えではありませんが、問題の原因を明らかにしTransactionTooLargeException、問題を特定するのに役立つ可能性があります。

ほとんどの回答は転送された大量のデータに言及していますが、重いスクロールとズームを行い、ActionBar スピナー メニューを繰り返し開いた後に、この例外が偶発的にスローされることがわかります。アクションバーをタップするとクラッシュします。(これはカスタム マッピング アプリです)

渡される唯一のデータは、「入力ディスパッチャー」からアプリへのタッチのようです。これは、「トランザクション バッファ」の 1 mb 近くに合理的に達することはできないと思います。

私のアプリはクアッド コア 1.6 GHz デバイスで実行されており、重量挙げに 3 つのスレッドを使用し、UI スレッド用に 1 つのコアを空けています。さらに、アプリは android:largeHeap を使用し、未使用のヒープが 10 MB 残っており、ヒープを拡張するためのスペースが 100 MB 残っています。だから私はそれがリソースの問題だとは言いません。

クラッシュの直前には、常に次の行が表示されます。

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

これは必ずしもその順序で印刷されるわけではありませんが、(私がチェックした限りでは)同じミリ秒で発生します。

そして、明確にするために、スタックトレース自体は質問と同じです:

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

Android One のソース コードを掘り下げると、次の行が見つかります。

フレームワーク/ベース/コア/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);

私には、トランザクションがTooLargeである以外の理由でトランザクションが失敗する、この文書化されていない機能にぶつかっている可能性があるように思えます。名前を付ける必要がありましたTransactionTooLargeOrAnotherReasonException

現時点では問題は解決していませんが、役に立つものが見つかった場合は、この回答を更新します。

更新:私のコードがいくつかのファイル記述子をリークしていることが判明しました。その数はLinuxで最大化され(通常は1024)、これが例外を引き起こしたようです。結局のところ、それはリソースの問題でした。これを 1024 回開いて検証した/dev/zeroところ、上記の例外や一部の SIGSEGV など、UI 関連のアクションであらゆる種類の奇妙な例外が発生しました。どうやらファイル/ソケットのオープンの失敗は、Android 全体で非常にきれいに処理/報告されるものではありません。

于 2013-01-17T12:22:16.653 に答える
12

この問題の特定の原因は 1 つではありません。私にとっては、Fragment クラスでこれを行っていました。

public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    super.onCreateView(inflater, container, savedInstanceState);
    View rootView = inflater.inflate(R.layout.snacks_layout, container); //<-- notice the absence of the false argument
    return rootView;
}

これの代わりに:

View rootView = inflater.inflate(R.layout.softs_layout, container, false);
于 2015-10-04T10:46:59.213 に答える
11

デバイスの機能やアプリに関係なく、トランザクション バッファーは 1 MB に制限されていることを理解することが重要です。このバッファは、作成するすべての API 呼び出しで使用され、アプリが現在実行しているすべてのトランザクション間で共有されます。

区画などの特定のオブジェクトも保持していると思うので、常にすべてを. と(Parcel.obtain())一致させることが重要です。obtain()recycle()

このエラーは、返されるデータが 1 MB 未満であっても (他のトランザクションがまだ実行されている場合)、大量のデータを返す API 呼び出しで簡単に発生する可能性があります。

たとえば、このPackageManager.getInstalledApplication()呼び出しは、インストールされているすべてのアプリのリストを返します。特定のフラグを追加すると、多くの余分なデータを取得できます。これを行うと失敗する可能性が高いため、余分なデータを取得せず、アプリごとに取得することをお勧めします。

ただし、呼び出しはまだ失敗する可能性があるためcatch、必要に応じて で囲み、再試行できるようにすることが重要です。

私の知る限り、再試行してできるだけ少ない情報を取得することを確認する以外に、このような問題の回避策はありません。

于 2013-11-23T16:27:24.490 に答える
9

私もSamsung S3でこの例外を受け取りました。私は2つの根本原因を疑っています、

  1. ロードして大量のメモリを消費するビットマップがある場合は、ダウンサイジングを使用してください
  2. drawable-_dpi フォルダーにいくつかのドローアブルがありません。Android はドローアブルでそれらを探してサイズを変更し、setContentView が突然ジャンプして大量のメモリを使用するようにします。

DDMS を使用してアプリを再生しながらヒープを確認すると、どの setcontentview が問題を引き起こしているかがわかります。

問題2を取り除くために、すべてのフォルダにすべてのドローアブルをコピーしました。

問題は解決しました。

于 2012-08-17T13:03:10.503 に答える
4

インテント経由でビットマップを送信しようとしたときに同じ問題に直面し、同時にそれが発生したときにアプリケーションを折りたたみました。

この記事でどのように説明されているかここにリンクの説明を入力してください これは、アクティビティが停止中の場合に発生します。つまり、後で復元するために安全に保管するために、アクティビティが保存された状態のバンドルをシステム OS に送信しようとしたことを意味します (構成の変更後)。またはプロセスの死)が、送信したバンドルの 1 つ以上が大きすぎました。

アクティビティで onSaveInstanceState をオーバーライドして、ハックで解決しました。

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

とコメントコールスーパー。これは汚いハックですが、完全に機能しています。ビットマップはクラッシュすることなく正常に送信されました。これが誰かを助けることを願っています。

于 2018-05-31T07:26:23.543 に答える
4

そのため、AIDL インターフェイスを介して大きすぎるオブジェクトをリモート サービスに送信しようとしていたことが原因でした。トランザクション サイズは 1MB を超えることはできません。要求は 512KB の個別のチャンクに分割され、インターフェイスを介して一度に 1 つずつ送信されます。私が知っている残忍な解決策ですが、ちょっと-そのAndroid :(

于 2012-09-19T21:21:47.400 に答える
3

これは、アクティビティ「A」にフラグメントが含まれている可能性があり、アクティビティ「B」に移動したときに発生する可能性があります。

アクティビティ「A」のアクティビティライフサイクルは

OnResume->OnPause()->OnSavedInsanceState()

ここで OnSavedInsanceState は、大量のデータで状態を保存できなかったため、クラッシュを引き起こす可能性があります。次のコードを追加して、アクティビティ「A」のsaveInsatnceをクリアしようとします。

 @Override
protected void onSaveInstanceState(Bundle oldInstanceState) {
    super.onSaveInstanceState(oldInstanceState);
    if (oldInstanceState != null) {
        oldInstanceState.clear();
    }

}
于 2021-01-12T15:26:28.623 に答える
2

私の場合、ネイティブ ライブラリが SIGSEGV でクラッシュした後、2 次クラッシュとして TransactionTooLargeException が発生します。ネイティブ ライブラリのクラッシュは報告されていないため、TransactionTooLargeException のみが発生します。

于 2015-08-11T21:32:54.847 に答える
1

大きなサイズのインテントオブジェクトデータを入れないように注意してください。私の場合、文字列500kサイズを追加してから、別のアクティビティを開始していました。この例外では常に失敗しました。アクティビティの静的変数を使用して、アクティビティ間でデータを共有することを避けました。Intentに送信してからプルする必要はありません。

私が持っていたもの:

String html = new String();//some string of 500K data.
Intent intent = new Intent(MainActivity.this, PageWebView.class);
//this is workaround - I just set static variable and then access it from another    activity.
MainActivity.htmlBody = timelineDb.getHTMLBodyForTweet(tweet);
//This line was present and it actually failed with the same exception you had.
//intent.putExtra("com.gladimdim.offtie.webview", html);
于 2013-01-14T22:40:13.693 に答える
1

これの根本的な原因を見つけました(mvdsが言うように、「ウィンドウの追加に失敗しました」とファイル記述子のリークの両方が発生しました)。

Android 4.4のバグがあります。とがに設定されているBitmapFactory.decodeFileDescriptor()場合にのみ発生します。これにより、ファイルとやり取りする多くの場所で多くの問題が発生します。inPurgeableinInputShareableBitmapOptionstrue

メソッドは からも呼び出されることに注意してくださいMediaStore.Images.Thumbnails.getThumbnail()

Universal Image Loaderは、この問題の影響を受けます。ピカソグライドは影響を受けないようです。 https://github.com/nostra13/Android-Universal-Image-Loader/issues/1020

于 2015-06-17T10:37:59.607 に答える
1

writeToParcel(Parcel dest, int flags) メソッドのこの 1 行のコードは、TransactionTooLargeException を取り除くのに役立ちました。

dest=Parcel.obtain(); 

このコードの後、すべてのデータをパーセル オブジェクト、つまり dest.writeInt() などに書き込みます。

于 2018-04-16T13:34:21.910 に答える
1

Android Espresso テストで Stackoverflow エラーから TransactionTooLargeException を受け取りました。アプリの Logcat フィルターを外したときに、ログに stackoverflow エラー スタック トレースが見つかりました。

非常に大きな例外スタックトレースを処理しようとすると、Espresso が TransactionTooLargeException を引き起こしたと推測しています。

于 2018-07-02T09:49:28.890 に答える
-6

別の考えられる原因:

で開始されるアクティビティがありましたonResume()。これにより、大量のトランザクションが発生し、電話 (Galaxy S2) が完全にフリーズ (ANR などなし) してから、ハード リセットが発生します。これは、それ自体が大きなバグのようなものです。

このコードで他の電話で何が起こるかを見るのは興味深いでしょう:

class MyActivity extends Activity
{
  // ...
  @Override
  void onResume()
  {
     super.onResume()
     startActivity(new Intent(this, MyActivity.class));
  }
}

そのコードを使うべきだと言っているのではありません。

于 2012-09-25T10:22:37.073 に答える