这是一个Android问题,也是一个Java问题。
我在活动中发现了一个自定义线程异常处理程序,如下所示:
public class MainActivity extends FlutterActivity {
public static String TAG = "MainActivity";
Thread thread;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Thread.setDefaultUncaughtExceptionHandler(new MyExceptionHandler(this));
thread = new Thread(new Runnable() {
public void run() {
try {
TimeUnit.SECONDS.sleep(25);
crashMe(); //Makes app crash
} catch (Exception exception) {
}
}
});
thread.start();
}
public void crashMe() {
throw new NullPointerException();
}
public void crashMe2() {
runOnUiThread(new Runnable() {
public void run() {
throw new NullPointerException();
}
});
}
}
正如您所看到的,在超时之后调用crashMe()
确实会使异常处理程序被调用。然而,一些颤振引擎的崩溃不会被我的处理程序和应用程序简单地关闭。就像这个:
2020-03-04 13:36:08.938 3901-3901/com.demo.flutter_app E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.demo.flutter_app, PID: 3901
java.lang.NullPointerException: Attempt to invoke virtual method 'android.view.DisplayAdjustments android.view.Display.getDisplayAdjustments()' on a null object reference
at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1900)
at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1636)
at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:7946)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:1092)
at android.view.Choreographer.doCallbacks(Choreographer.java:893)
at android.view.Choreographer.doFrame(Choreographer.java:812)
at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:1078)
at android.os.Handler.handleCallback(Handler.java:907)
at android.os.Handler.dispatchMessage(Handler.java:105)
at android.os.Looper.loop(Looper.java:216)
at android.app.ActivityThread.main(ActivityThread.java:7625)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:524)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:987)
其中使用的是实验颤振网视图。
我怎么能绝对捕捉到所有的撞车?我希望能够在任何时候重新启动应用程序,但是有些崩溃是无法处理的。
更新:
下面是另一个它无法处理的崩溃:
[+1520 ms] F/libc (31305): Fatal signal 6 (SIGABRT), code -6 (SI_TKILL) in tid 31351 (RenderThread), pid 31305 (com.example.bug)
[ +184 ms] *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
[ ] Build fingerprint: 'Dragon_Touch/M7/M7:9/PPR2.181005.003/ysq20190426:user/release-keys'
[ ] Revision: '0'
[ ] ABI: 'arm64'
[ ] pid: 31305, tid: 31351, name: RenderThread >>> com.example.bug <<<
[ ] signal 6 (SIGABRT), code -6 (SI_TKILL), fault addr --------
[ ] Abort message: 'Failed to set damage region on surface 0x7a1391d400, error=EGL_BAD_ACCESS'
[ ] x0 0000000000000000 x1 0000000000007a77 x2 0000000000000006 x3 0000000000000008
[ ] x4 feff71647164636d x5 feff71647164636d x6 feff71647164636d x7 7f7f7f7f7f7f7f7f
[ ] x8 0000000000000083 x9 0000007abf876718 x10 fffffff87ffffbdf x11 0000000000000001
[ ] x12 0000007a1f57ebd0 x13 ffffffffffffffff x14 ffffffffff000000 x15 ffffffffffffffff
[ ] x16 0000007abf8b22b0 x17 0000007abf7f0298 x18 0000007a1f57e3ba x19 0000000000007a49
[ ] x20 0000000000007a77 x21 0000000000000083 x22 0000007a1a8a1bb0 x23 0000007a1f57f1b0
[ ] x24 0000000000000000 x25 0000007a1a8a1b24 x26 0000007a1f57f198 x27 0000007a1a8a1b22
[ +2 ms] x28 0000000000000000 x29 0000007a1f57eaf0
[ +1 ms] sp 0000007a1f57eab0 lr 0000007abf7e4a50 pc 0000007abf7e4a7c
[ +82 ms] backtrace:
[ ] #00 pc 0000000000021a7c /system/lib64/libc.so (abort+124)
[ ] #01 pc 00000000000080f8 /system/lib64/liblog.so (__android_log_assert+296)
[ ] #02 pc 0000000000486e64 /system/lib64/libhwui.so (android::uirenderer::renderthread::EglManager::damageFrame(android::uirenderer::renderthread::Frame const&, SkRect const&)+180)
[ ] #03 pc 0000000000480858 /system/lib64/libhwui.so (android::uirenderer::skiapipeline::SkiaOpenGLPipeline::draw(android::uirenderer::renderthread::Frame const&, SkRect const&, SkRect const&,
android::uirenderer::FrameBuilder::LightGeometry const&, android::uirenderer::LayerUpdateQueue*, android::uirenderer::Rect const&, bool, bool, android::uirenderer::BakedOpRenderer::LightInfo const&,
std::__1::vector<android::sp<android::uirenderer::RenderNode>, std::__1::allocator<android::sp<android::uirenderer::Re
[ +1 ms] #04 pc 0000000000108728 /system/lib64/libhwui.so (android::uirenderer::renderthread::CanvasContext::draw()+192)
[ ] #05 pc 0000000000485854 /system/lib64/libhwui.so
(_ZNSt3__110__function6__funcIZN7android10uirenderer12renderthread13DrawFrameTask11postAndWaitEvE3$_0NS_9allocatorIS6_EEFvvEEclEv$c303f2d2360db58ed70a2d0ac7ed911b+644)
[ ] #06 pc 000000000043c5a8 /system/lib64/libhwui.so (android::uirenderer::WorkQueue::process()+168)
[ ] #07 pc 0000000000115e5c /system/lib64/libhwui.so (android::uirenderer::renderthread::RenderThread::threadLoop()+244)
[ ] #08 pc 000000000000fb80 /system/lib64/libutils.so (android::Thread::_threadLoop(void*)+280)
[ ] #09 pc 00000000000830d4 /system/lib64/libc.so (__pthread_start(void*)+36)
[ ] #10 pc 000000000002337c /system/lib64/libc.so (__start_thread+68)
发布于 2020-04-09 09:05:09
编辑-对评论的答复
即使有一个try - catch
子句,异常也可能以任何方式抛出--当代码隐式地或显式地抛出catch
块内的异常时,它将不会由自定义UncaughtExceptionHandler
处理
所有未处理的异常(没有try - catch
包装器)和没有自定义UncaughtExceptionHandler
的异常都将由默认的异常处理。
就Android而言,C代码中的异常很难处理和捕获--最好的方法是将它们传播到android代码并在那里处理它们--但它只适用于C代码,而不适用于某些第三方库。如果没有这样的传播,并且异常是终端--即使使用默认的UncaughtExceptionHandler
,应用程序也会在没有任何正确的错误管理的情况下迅速和意外地停止。
您刚才所问到的错误与Java和C都有一点不同。如您所见,它发生在RenderThread上,因此它直接连接到代码的CPU和GPU执行。在安卓系统中,有几种在这种情况下工作的方法:OpenGl
、Vulkan
、RenderScript
、OpenCl
等。
颤振框架使用GPU渲染范式,因此它基本上可以像游戏一样工作在智能手机上。我可以假设它使用了一些描述过的技术来呈现UI(我认为它是OpenGL
,因为它被大多数设备开箱即用,尽管它可能是某种组合)。
您发布的错误基本上是C错误,但它是RenderThread中的一个错误,因此它是由GPU或CPU不正确的命令执行引起的。
颤振可以以正确的方式处理一些这样的错误,并给出一个人类可读的解决方案。但在这种情况下就不是了。
对不起,伙计,没办法抓到这个错误。但它并不像NullPoitnerException
那样被捕获--这些例外表明,一些问题应该由开发人员解决,而不是通过简单的重新启动应用程序来隐藏。
编辑端
问题是-在Java中没有“绝对捕获所有崩溃”这样的东西。这就是JVM的预期行为。
虽然setDefaultUncaughtExceptionHandler
在大多数情况下都应该工作,但在以下情况下它将无法工作:
setDefaultUncaughtExceptionHandler
是在您的代码之外的某个地方使用的(或者是在有自己的处理程序的线程上发生了一个未察觉的异常),它处理了您想要捕获的异常--由try - catch
子句UncaughtExceptionHandler
中显示一些东西(对话框或吐司)--这是非常不推荐的,因为如果异常发生在UI线程上,应用程序可能会冻结异常,如果异常发生在非UI线程上--当试图显示对话框时,您将收到一个未显示的异常,因为您只能在UI线程上显示一些东西。H 226F 227
有更多的情况,但这些不能应用到Android,因为这些是网络的具体情况。
同样,flutter也有自己的异常处理机制--因此flutter框架异常可能不会按照您预期的方式使用自定义UncaughtExceptionHandler
来处理。
因此,基本上没有办法清楚地捕捉到Android应用程序中的所有异常。即使是Crashlitycs也无法将它们全部捕获,并且使用了基于本机(C)的方法。
希望能帮上忙。
https://stackoverflow.com/questions/61069052
复制相似问题