WindowManagerGlobal 的 setStoppedState 内的 IndexOutOfBoundsException
IndexOutOfBoundsException inside setStoppedState of WindowManagerGlobal
我们应用程序中的最高崩溃仅发生在 Android 9 上,并且仅发生在少数设备上,例如中兴、TCL、海信、BLU、现代。
由于我们无权访问这些设备中的任何一个,因此我们无法重现此问题,并且由于它发生在 Android 框架内,我们不确定这是我们代码中的错误(虽然它必须是,因为我们在 Whosebug 中找不到任何类似的崩溃)。
Fatal Exception: java.lang.RuntimeException: Unable to stop activity {MyActivity}: java.lang.IndexOutOfBoundsException: Index: 0, Size: 0
at android.app.ActivityThread.callActivityOnStop(ActivityThread.java:4213)
at android.app.ActivityThread.performStopActivityInner(ActivityThread.java:4183)
at android.app.ActivityThread.handleStopActivity(ActivityThread.java:4263)
at android.app.servertransaction.TransactionExecutor.performLifecycleSequence(TransactionExecutor.java:192)
at android.app.servertransaction.TransactionExecutor.cycleToPath(TransactionExecutor.java:165)
at android.app.servertransaction.TransactionExecutor.executeLifecycleState(TransactionExecutor.java:142)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:70)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1816)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:193)
at android.app.ActivityThread.main(ActivityThread.java:6852)
at java.lang.reflect.Method.invoke(Method.java)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:504)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)
Caused by java.lang.IndexOutOfBoundsException: Index: 0, Size: 0
at java.util.ArrayList.get(ArrayList.java:437)
at android.view.WindowManagerGlobal.setStoppedState(WindowManagerGlobal.java:604)
at android.app.Activity.performStop(Activity.java:8831)
at android.app.ActivityThread.callActivityOnStop(ActivityThread.java:4205)
at android.app.ActivityThread.performStopActivityInner(ActivityThread.java:4183)
at android.app.ActivityThread.handleStopActivity(ActivityThread.java:4263)
at android.app.servertransaction.TransactionExecutor.performLifecycleSequence(TransactionExecutor.java:192)
at android.app.servertransaction.TransactionExecutor.cycleToPath(TransactionExecutor.java:165)
at android.app.servertransaction.TransactionExecutor.executeLifecycleState(TransactionExecutor.java:142)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:70)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1816)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:193)
at android.app.ActivityThread.main(ActivityThread.java:6852)
at java.lang.reflect.Method.invoke(Method.java)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:504)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)
有没有人经历过类似的崩溃,或者知道根本原因可能是什么?
这里是the code where the crash happens:
public void setStoppedState(IBinder token, boolean stopped) {
synchronized (mLock) {
int count = mViews.size();
for (int i = 0; i < count; i++) {
if (token == null || mParams.get(i).token == token) {
ViewRootImpl root = mRoots.get(i);
root.setWindowStopped(stopped);
}
}
}
}
(行号与您的异常信息不完全匹配,因为我不知道您的设备使用的代码的确切版本。)
假设我们可以预期 mViews
、mParams
和 mRoots
的长度相同,则此代码看起来是正确的。
然而,如果我们在 git 历史中向前移动一点,我们会发现 commit 978e7f87:
From: tetsutoki.shiozawa@sony.com
Subject: Fix: WindowManagerGlobal#setStoppedState failed by IOOBE
Symptom:
An application crashed due to IndexOutOfBoundsException.
The exception was thrown at WindowManagerGlobal#setStoppedState.
Root cause:
setStoppedState invokes setWindowStopped for each ViewRoot by
ascending order. If an application removes its view within the
loop, loop index exceeds the number of items.
Solution:
Loop in descending order.
我假设您看到崩溃的设备不包含此提交,而没有问题的设备包含此提交。
新代码如下所示:
public void setStoppedState(IBinder token, boolean stopped) {
synchronized (mLock) {
int count = mViews.size();
for (int i = count - 1; i >= 0; i--) {
if (token == null || mParams.get(i).token == token) {
ViewRootImpl root = mRoots.get(i);
// Client might remove the view by "stopped" event.
root.setWindowStopped(stopped);
}
}
}
}
由于您无法影响相关设备,因此您需要解决此问题。提交消息为我们指明了一个明确的方向:确保您没有删除此处发生的回调中的视图。
我们应用程序中的最高崩溃仅发生在 Android 9 上,并且仅发生在少数设备上,例如中兴、TCL、海信、BLU、现代。
由于我们无权访问这些设备中的任何一个,因此我们无法重现此问题,并且由于它发生在 Android 框架内,我们不确定这是我们代码中的错误(虽然它必须是,因为我们在 Whosebug 中找不到任何类似的崩溃)。
Fatal Exception: java.lang.RuntimeException: Unable to stop activity {MyActivity}: java.lang.IndexOutOfBoundsException: Index: 0, Size: 0
at android.app.ActivityThread.callActivityOnStop(ActivityThread.java:4213)
at android.app.ActivityThread.performStopActivityInner(ActivityThread.java:4183)
at android.app.ActivityThread.handleStopActivity(ActivityThread.java:4263)
at android.app.servertransaction.TransactionExecutor.performLifecycleSequence(TransactionExecutor.java:192)
at android.app.servertransaction.TransactionExecutor.cycleToPath(TransactionExecutor.java:165)
at android.app.servertransaction.TransactionExecutor.executeLifecycleState(TransactionExecutor.java:142)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:70)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1816)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:193)
at android.app.ActivityThread.main(ActivityThread.java:6852)
at java.lang.reflect.Method.invoke(Method.java)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:504)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)
Caused by java.lang.IndexOutOfBoundsException: Index: 0, Size: 0
at java.util.ArrayList.get(ArrayList.java:437)
at android.view.WindowManagerGlobal.setStoppedState(WindowManagerGlobal.java:604)
at android.app.Activity.performStop(Activity.java:8831)
at android.app.ActivityThread.callActivityOnStop(ActivityThread.java:4205)
at android.app.ActivityThread.performStopActivityInner(ActivityThread.java:4183)
at android.app.ActivityThread.handleStopActivity(ActivityThread.java:4263)
at android.app.servertransaction.TransactionExecutor.performLifecycleSequence(TransactionExecutor.java:192)
at android.app.servertransaction.TransactionExecutor.cycleToPath(TransactionExecutor.java:165)
at android.app.servertransaction.TransactionExecutor.executeLifecycleState(TransactionExecutor.java:142)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:70)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1816)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:193)
at android.app.ActivityThread.main(ActivityThread.java:6852)
at java.lang.reflect.Method.invoke(Method.java)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:504)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)
有没有人经历过类似的崩溃,或者知道根本原因可能是什么?
这里是the code where the crash happens:
public void setStoppedState(IBinder token, boolean stopped) {
synchronized (mLock) {
int count = mViews.size();
for (int i = 0; i < count; i++) {
if (token == null || mParams.get(i).token == token) {
ViewRootImpl root = mRoots.get(i);
root.setWindowStopped(stopped);
}
}
}
}
(行号与您的异常信息不完全匹配,因为我不知道您的设备使用的代码的确切版本。)
假设我们可以预期 mViews
、mParams
和 mRoots
的长度相同,则此代码看起来是正确的。
然而,如果我们在 git 历史中向前移动一点,我们会发现 commit 978e7f87:
From: tetsutoki.shiozawa@sony.com
Subject: Fix: WindowManagerGlobal#setStoppedState failed by IOOBE
Symptom:
An application crashed due to IndexOutOfBoundsException.
The exception was thrown at WindowManagerGlobal#setStoppedState.
Root cause:
setStoppedState invokes setWindowStopped for each ViewRoot by
ascending order. If an application removes its view within the
loop, loop index exceeds the number of items.
Solution:
Loop in descending order.
我假设您看到崩溃的设备不包含此提交,而没有问题的设备包含此提交。
新代码如下所示:
public void setStoppedState(IBinder token, boolean stopped) {
synchronized (mLock) {
int count = mViews.size();
for (int i = count - 1; i >= 0; i--) {
if (token == null || mParams.get(i).token == token) {
ViewRootImpl root = mRoots.get(i);
// Client might remove the view by "stopped" event.
root.setWindowStopped(stopped);
}
}
}
}
由于您无法影响相关设备,因此您需要解决此问题。提交消息为我们指明了一个明确的方向:确保您没有删除此处发生的回调中的视图。