首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何为安卓应用程序中的所有线程设置uncaugthExceptionHandler?只有在某些情况下才会发生碰撞。

如何为安卓应用程序中的所有线程设置uncaugthExceptionHandler?只有在某些情况下才会发生碰撞。
EN

Stack Overflow用户
提问于 2020-04-06 21:11:14
回答 1查看 848关注 0票数 3

这是一个Android问题,也是一个Java问题。

我在活动中发现了一个自定义线程异常处理程序,如下所示:

代码语言:javascript
运行
复制
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()确实会使异常处理程序被调用。然而,一些颤振引擎的崩溃不会被我的处理程序和应用程序简单地关闭。就像这个:

代码语言:javascript
运行
复制
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)

其中使用的是实验颤振网视图。

我怎么能绝对捕捉到所有的撞车?我希望能够在任何时候重新启动应用程序,但是有些崩溃是无法处理的。

更新:

下面是另一个它无法处理的崩溃:

代码语言:javascript
运行
复制
[+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)
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-04-09 09:05:09

编辑-对评论的答复

即使有一个try - catch子句,异常也可能以任何方式抛出--当代码隐式地或显式地抛出catch块内的异常时,它将不会由自定义UncaughtExceptionHandler处理

所有未处理的异常(没有try - catch包装器)和没有自定义UncaughtExceptionHandler的异常都将由默认的异常处理。

就Android而言,C代码中的异常很难处理和捕获--最好的方法是将它们传播到android代码并在那里处理它们--但它只适用于C代码,而不适用于某些第三方库。如果没有这样的传播,并且异常是终端--即使使用默认的UncaughtExceptionHandler,应用程序也会在没有任何正确的错误管理的情况下迅速和意外地停止。

您刚才所问到的错误与Java和C都有一点不同。如您所见,它发生在RenderThread上,因此它直接连接到代码的CPU和GPU执行。在安卓系统中,有几种在这种情况下工作的方法:OpenGlVulkanRenderScriptOpenCl等。

颤振框架使用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)的方法。

希望能帮上忙。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/61069052

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档