Ixx*_*Ixx 225 android exception
我得到了一个应用程序TransactionTooLargeException的错误跟踪.不可重复,从未有过.在文档中说
Binder事务失败,因为它太大了.
在远程过程调用期间,调用的参数和返回值将作为存储在Binder事务缓冲区中的Parcel对象传输.如果参数或返回值太大而不适合事务缓冲区,则调用将失败并抛出TransactionTooLargeException.
...
当远程过程调用抛出TransactionTooLargeException时,有两种可能的结果.客户端无法将其请求发送到服务(很可能,如果参数太大而无法放入事务缓冲区中),或者服务无法将其响应发送回客户端(最有可能的话,如果返回值为太大而不适合事务缓冲区).
...
所以,好吧,我正在传递或接收超出某个未知限制的参数.但是哪里?
堆栈跟踪不会显示我的文件中的任何内容:
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)
Run Code Online (Sandbox Code Playgroud)
它似乎与视图有关,因为所有的Window/View行?这与远程过程调用有什么关系?我该如何查找此错误的原因?
在应用程序中我只使用Webservices,我没有使用Service类,Web服务是"远程过程调用"还是其他可能......?
PS也许它很重要:Android版本:4.0.3,设备:HTC One X.
Dur*_*amy 149
我遇到了这个问题,我发现当服务和应用程序之间交换大量数据时(这涉及传输大量缩略图).实际上数据大小约为500kb,IPC事务缓冲区大小设置为1024KB.我不确定为什么它超出了事务缓冲区.
当您通过intent extras传递大量数据时,也会发生这种情况
当您在应用程序中遇到此异常时,请分析您的代码.
当你得到这个例外时如何处理
如果可能,将大操作拆分为小块,例如,而不是使用1000次操作调用applyBatch(),每次调用100.
不要在服务和应用程序之间交换大量数据(> 1MB)
我不知道该怎么做,但是,不要查询android,它可以返回大量数据:-)
mvd*_*vds 40
这不是一个明确的答案,但它可能会对a的原因有所了解TransactionTooLargeException并帮助查明问题.
虽然大多数答案都涉及大量传输的数据,但我看到在重度滚动和缩放以及重复打开ActionBar微调器菜单后偶然抛出此异常.点击操作栏时会发生崩溃.(这是一个自定义地图应用程序)
传递的唯一数据似乎是从"输入调度程序"到应用程序的触摸.我认为在"事务缓冲区"中这不可能合理地接近1 mb.
我的应用程序运行在四核1.6 GHz设备上,并使用3个线程进行重载,为UI线程保留一个核心.此外,该应用程序使用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 !!!
Run Code Online (Sandbox Code Playgroud)
哪个不是按顺序打印的,但是(据我检查)在同一毫秒内发生.
为清楚起见,堆栈跟踪本身与问题中的相同:
E/AndroidRuntime(28182): java.lang.RuntimeException: Adding window failed
..
E/AndroidRuntime(28182): Caused by: android.os.TransactionTooLargeException
Run Code Online (Sandbox Code Playgroud)
深入研究android的源代码,找到以下几行:
框架/碱/核心/ 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);
Run Code Online (Sandbox Code Playgroud)
对我而言,听起来我可能正在使用这个未记录的功能,其中交易因其他原因而失败,而不是事务是TooLarge.他们应该命名它TransactionTooLargeOrAnotherReasonException.
这时我没有解决问题,但如果我发现有用的东西,我会更新这个答案.
更新:事实证明我的代码泄漏了一些文件描述符,其数量在linux中最大化(通常为1024),这似乎触发了异常.毕竟这是一个资源问题.我通过打开/dev/zero1024次验证了这一点,这导致了UI相关操作中的各种奇怪异常,包括上面的异常,甚至一些SIGSEGV.显然无法打开文件/套接字并不是在Android中非常干净地处理/报告的内容.
sul*_*lai 34
如果您需要调查导致崩溃的Parcel,您应该考虑尝试使用TooLargeTool.
(我发现这是@Max Spencer根据接受的答案发表的评论,这对我的情况很有帮助.)
小智 33
本TransactionTooLargeException一直是困扰我们约4个月,现在,我们终于解决了这个问题!
发生的事情是我们正在使用FragmentStatePagerAdaptera ViewPager.用户可以翻阅并创建100多个片段(它是一个阅读应用程序).
虽然我们正确地管理了片段destroyItem(),但在Androids实现中FragmentStatePagerAdapter存在一个bug,它保留了对以下列表的引用:
private ArrayList<Fragment.SavedState> mSavedState = new ArrayList<Fragment.SavedState>();
Run Code Online (Sandbox Code Playgroud)
当Android FragmentStatePagerAdapter试图保存状态时,它会调用该函数
@Override
public Parcelable saveState() {
Bundle state = null;
if (mSavedState.size() > 0) {
state = new Bundle();
Fragment.SavedState[] fss = new Fragment.SavedState[mSavedState.size()];
mSavedState.toArray(fss);
state.putParcelableArray("states", fss);
}
for (int i=0; i<mFragments.size(); i++) {
Fragment f = mFragments.get(i);
if (f != null && f.isAdded()) {
if (state == null) {
state = new Bundle();
}
String key = "f" + i;
mFragmentManager.putFragment(state, key, f);
}
}
return state;
}
Run Code Online (Sandbox Code Playgroud)
正如您所看到的,即使您正确地管理FragmentStatePagerAdapter子类中的片段,基类仍将Fragment.SavedState为每个创建的片段存储一个.将该TransactionTooLargeException数组转储到a parcelableArray并且操作系统不喜欢100多个项目时会发生这种情况.
因此,我们的修复是覆盖saveState()方法而不是存储任何东西"states".
@Override
public Parcelable saveState() {
Bundle bundle = (Bundle) super.saveState();
bundle.putParcelableArray("states", null); // Never maintain any states from the base class, just null it out
return bundle;
}
Run Code Online (Sandbox Code Playgroud)
Yaz*_*006 19
对于那些因为查找TransactionTooLargeException异常的答案而感到极度失望的人,请尝试检查在实例状态中保存的内容.
在compile/targetSdkVersion <= 23上,我们只有关于大型保存状态的内部警告,但没有任何内容崩溃:
E/ActivityThread: App sent too much data in instance state, so it was ignored
android.os.TransactionTooLargeException: data parcel size 713856 bytes
at android.os.BinderProxy.transactNative(Native Method)
at android.os.BinderProxy.transact(Binder.java:615)
at android.app.ActivityManagerProxy.activityStopped(ActivityManagerNative.java:3604)
at android.app.ActivityThread$StopInfo.run(ActivityThread.java:3729)
at android.os.Handler.handleCallback(Handler.java:751)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6044)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:865)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:755)
Run Code Online (Sandbox Code Playgroud)
但是在compile/targetSdkVersion> = 24上,我们在这种情况下遇到了真正的RuntimeException崩溃:
java.lang.RuntimeException: android.os.TransactionTooLargeException: data parcel size 713860 bytes
at android.app.ActivityThread$StopInfo.run(ActivityThread.java:3737)
at android.os.Handler.handleCallback(Handler.java:751)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6044)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:865)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:755)
Caused by: android.os.TransactionTooLargeException: data parcel size 713860 bytes
at android.os.BinderProxy.transactNative(Native Method)
at android.os.BinderProxy.transact(Binder.java:615)
at android.app.ActivityManagerProxy.activityStopped(ActivityManagerNative.java:3604)
at android.app.ActivityThread$StopInfo.run(ActivityThread.java:3729)
at android.os.Handler.handleCallback(Handler.java:751)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6044)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:865)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:755)
Run Code Online (Sandbox Code Playgroud)
该怎么办?
将数据保存在本地数据库中,并仅将id保存在实例状态,您可以使用该状态来检索此数据.
ojo*_*ifu 11
这个问题没有一个具体原因.对我来说,在我的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;
}
Run Code Online (Sandbox Code Playgroud)
而不是这个:
View rootView = inflater.inflate(R.layout.softs_layout, container, false);
Run Code Online (Sandbox Code Playgroud)
Vai*_*den 11
将应用程序发送到后台时,通常会抛出此异常.
所以我决定使用数据Fragment方法来完全规避onSavedInstanceStae生命周期.我的解决方案还处理复杂的实例状态并尽快释放内存.
首先,我创建了一个简单的Fargment来存储数据:
package info.peakapps.peaksdk.logic;
import android.app.Fragment;
import android.app.FragmentManager;
import android.os.Bundle;
/**
* A neat trick to avoid TransactionTooLargeException while saving our instance state
*/
public class SavedInstanceFragment extends Fragment {
private static final String TAG = "SavedInstanceFragment";
private Bundle mInstanceBundle = null;
public SavedInstanceFragment() { // This will only be called once be cause of setRetainInstance()
super();
setRetainInstance( true );
}
public SavedInstanceFragment pushData( Bundle instanceState )
{
if ( this.mInstanceBundle == null ) {
this.mInstanceBundle = instanceState;
}
else
{
this.mInstanceBundle.putAll( instanceState );
}
return this;
}
public Bundle popData()
{
Bundle out = this.mInstanceBundle;
this.mInstanceBundle = null;
return out;
}
public static final SavedInstanceFragment getInstance(FragmentManager fragmentManager )
{
SavedInstanceFragment out = (SavedInstanceFragment) fragmentManager.findFragmentByTag( TAG );
if ( out == null )
{
out = new SavedInstanceFragment();
fragmentManager.beginTransaction().add( out, TAG ).commit();
}
return out;
}
}
Run Code Online (Sandbox Code Playgroud)
然后在我的主要Activity上完全绕过保存的实例循环,并将respoinsibilty推迟到我的数据Fragment.无需在Fragments本身上使用它,sice将其状态自动添加到Activity的状态中:
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
SavedInstanceFragment.getInstance( getFragmentManager() ).pushData( (Bundle) outState.clone() );
outState.clear(); // We don't want a TransactionTooLargeException, so we handle things via the SavedInstanceFragment
}
Run Code Online (Sandbox Code Playgroud)
剩下的就是弹出保存的实例:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(SavedInstanceFragment.getInstance(getFragmentManager()).popData());
}
@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState( SavedInstanceFragment.getInstance( getFragmentManager() ).popData() );
}
Run Code Online (Sandbox Code Playgroud)
详细信息:http://www.devsbedevin.com/avoiding-transactiontoolargeexception-on-android-nougat-and-up/
我也在三星S3上遇到这个例外.我怀疑有两个根本原因,
使用DDMS并在播放应用程序时查看堆,这将为您提供有关setcontentview创建问题的一些指示.
我复制了所有文件夹中的所有drawables以摆脱问题2.
问题已解决.
重要的是要了解事务缓冲区限制为1 MB,无论设备功能或应用程序如何.此缓冲区用于您进行的每个API调用,并在应用程序当前正在运行的所有事务中共享.
我相信它也有一些像parcels这样的特定对象(Parcel.obtain()),所以始终将每个对象obtain()与a 匹配很重要recycle().
即使返回的数据小于1 MB(如果其他事务仍在运行),返回大量数据的API调用也很容易发生此错误.
例如,该PackageManager.getInstalledApplication()调用返回所有已安装应用程序的列表.添加特定标志允许检索大量额外数据.这样做可能会失败,因此建议不要检索任何额外的数据并按应用程序检索这些数据.
然而,呼叫可能仍然失败,因此用a围绕它catch并且必要时能够重试是很重要的.
据我所知,除了重试并确保尽可能少地检索信息之外,没有解决此类问题的方法.
小智 8
这可能会发生,因为活动“A”可能有片段,并且当您导航到活动“B”时。
那么活动“A”的活动生命周期将是
OnResume->OnPause()->OnSavedInsanceState()
OnSavedInsanceState 中的此处可能会导致崩溃,因为它无法保存太多数据的状态。因此,尝试通过添加以下代码来清除活动“A”的 saveInsatnce 。
@Override
protected void onSaveInstanceState(Bundle oldInstanceState) {
super.onSaveInstanceState(oldInstanceState);
if (oldInstanceState != null) {
oldInstanceState.clear();
}
}
Run Code Online (Sandbox Code Playgroud)
小智 8
我们的应用程序也有这个问题。经过测试发现,当应用内存不足,activity被回收时,系统调用onSaveInstanceState方法保存大量bundle数据,每次数据都会变大,最终会报TransactionTooLargeException错误,所以我觉得这个方法应该可以解决这个问题。
public final int MAX_BUNDLE_SIZE = 300;
@Override
protected void onSaveInstanceState(@NonNull Bundle outState) {
super.onSaveInstanceState(outState);
long bundleSize = getBundleSize(outState);
if (bundleSize > MAX_BUNDLE_SIZE * 1024) {
outState.clear();
}
}
private long getBundleSize(Bundle bundle) {
long dataSize;
Parcel obtain = Parcel.obtain();
try {
obtain.writeBundle(bundle);
dataSize = obtain.dataSize();
} finally {
obtain.recycle();
}
return dataSize;
}
Run Code Online (Sandbox Code Playgroud)
将此添加到您的活动
@Override
protected void onSaveInstanceState(Bundle oldInstanceState) {
super.onSaveInstanceState(oldInstanceState);
oldInstanceState.clear();
}
Run Code Online (Sandbox Code Playgroud)
它对我有用,希望对您也有帮助
| 归档时间: |
|
| 查看次数: |
152650 次 |
| 最近记录: |