• 张绍文 置顶
    2018-12-04
    补充一下获得logcat和Jave堆栈的方法:
    一. 获取logcat
    logcat日志流程是这样的,应用层 --> liblog.so --> logd,底层使用ring buffer来存储数据。
    获取的方式有以下三种:
       1. 通过logcat命令获取。
       优点:非常简单,兼容性好。
       缺点:整个链路比较长,可控性差,失败率高,特别是堆破坏或者堆内存不足时,基本会失败。
       2. hook liblog.so实现。通过hook liblog.so 中__android_log_buf_write 方法,将内容重定向到自己的buffer中。
       优点:简单,兼容性相对还好。
       缺点:要一直打开。
       3. 自定义获取代码。通过移植底层获取logcat的实现,通过socket直接跟logd交互。
       优点:比较灵活,预先分配好资源,成功率也比较高。
       缺点:实现非常复杂

    二. 获取Java 堆栈
       native崩溃时,通过unwind只能拿到Native堆栈。我们希望可以拿到当时各个线程的Java堆栈
       1. Thread.getAllStackTraces()。
        优点:简单,兼容性好。
        缺点:
            a. 成功率不高,依靠系统接口在极端情况也会失败。
            b. 7.0之后这个接口是没有主线程堆栈。
            c. 使用Java层的接口需要暂停线程
       2. hook libart.so。通过hook ThreadList和Thread的函数,获得跟ANR一样的堆栈。为了稳定性,我们会在fork子进程执行。
       优点:信息很全,基本跟ANR的日志一样,有native线程状态,锁信息等等。
       缺点:黑科技的兼容性问题,失败时可以用Thread.getAllStackTraces()兜底

    获取Java堆栈的方法还可以用在卡顿时,因为使用fork进程,所以可以做到完全不卡主进程。这块我们在后面会详细的去讲。
    展开
     1
     65
  • 小龙虾
    2018-12-04
    老师可能还不了解学生的水平,读者都是做应用层程序的你讲这么深入恐怕没什么效果

    作者回复: 不会的,移动开发已经十年了,已经不是单独写个界面就可以了。应用层开发当你深入到后面,这些知识都是必须的。当你知道了更多,学习的更多深入的时候,你才能做一些别人做不了的东西。

    
     45
  • Stefan
    2018-12-07
    回答github上的问题:
    通过对比Android 6.0前后的源码发现,FinalizerWatchdogDaemon调用的是父类Deamon中的stop方法,区别在于:
    //6.0之前
    ...
    threadToStop.interrupt();
    ...
    //>=6.0
    ...
    interrupt(threadToStop);
    ...
    public synchronized void interrupt(Thread thread) {
        if (thread == null) {
            throw new IllegalStateException("not running");
        }
        thread.interrupt();
    }
    ...
    可以发现区别在于6.0之前调用threadToStop的interrupt方法是没有加锁的,所以可能会有线程同步的问题。
    PS:推荐一个在线看源码的网站,包括1.6到9.0全部的源码:http://androidxref.com/
    展开
     2
     18
  • arvinljw
    2018-12-04
    张老师好,我想问一下,感觉学习这些课有点理解不了,不知道为什么,应该怎么入手呢?

    作者回复: 坚持,可能跟着学习完整个课程再回头看会有不一样的感觉

    
     15
  • HI
    2018-12-04
    貌似目前NDK中对于错误的检查还不够完善,比如对于函数的返回值,写了一个函数本身要写返回值,后面忘记写了发现IDE没有提示,并且能编译通过,但是在运行的时候会出现崩溃,而且崩溃的信息非常少,貌似就记得最后一行signal 6 还是 signal -1,当时的我看到这个是非常蒙逼的,大量的回退代码,添加日志,勉强找到,要是早点知道signal ,拿着对应的code对比,可能没那么痛苦
    
     12
  • Find
    2018-12-05
    上一篇运行出啦后还没有达到最终效果,下一篇都出来了,Android开发5年都是应用层开发,突然一下这么深入感觉很难适应,真心建议由浅到深讲解下,针对例子可以讲解一下。
    
     11
  • 尛鬼
    2018-12-28
    文哥,对于大多在应用层上开发的程序员来说,涉及到native的代码难度高了好多,其实也不是我们不想学,很多时候是因为没有这样的环境锻炼我们,再多的自学,没有一个真正项目的磨炼,这些知识很难巩固和加深,缺少关键性的实战经验,我自学过C/C++好几个月,但是没有任何一个项目可以让我实践学习,没有一个项目告诉我的代码是否有问题,是否有性能问题等等,就是因为这样,让我不知道该如何学习,该向哪个方向进阶,文哥,可以指导一下么?
     1
     7
  • O_o
    2018-12-05
    感觉可以由浅入深的讲,这一脚下去有点深呀,可能很多人3,4年经验,没做过这方面,学完了这一章一脸蒙圈,也没太大帮助呀

    作者回复: 一脸懵逼没有关系,我们可以跟着文中提到的一些文件,去学习到linux的一些基础知识。这些文件记录了一些什么样的内容,对排查问题有什么帮助,怎么在应用获取它们。

    后面的内容会从浅入深,我们学习完整个专栏再回头看应该有不同的感觉

    
     7
  • mzh
    2018-12-06
    之前遇到过一个输入法的内存泄露,但是自己完全没有调用过输入法,后面查了一下 网上说是系统的一个bug 张老师 这种应该怎么解决呢?

    作者回复: 那个问题很经典,解决方法就是反射将输入法的两个view置空

    
     6
  • Kenny
    2018-12-04
    张老师,看到你解决一些棘手的崩溃,会去翻看源码,然后对比版本的差异,然后寻找hook点去解决,这个要考虑机型适配吧?毕竟国产机型rom差异化严重。

    作者回复: Hook的时候,前几个版本一般会把hook失败的机型 rom 堆栈传上来做进一步分析。top的机型也会保证可以兼容

    
     5
  • 久九
    2019-02-18
    1.通过Bugly查看崩溃日志,确定问题所在,google或者自行调试解决问题。2.通过sample的练习,梳理了反射和代理相关的知识,学会了通过寻找Hook点来处理Bug的这种思维(以前完全没有这方面的概念,汗颜!!)
    
     3
  • 山鬼
    2018-12-19
    感觉大量的问题,在被定位出来以后,解决办法就是去读代码就好了,包括课后习题的例子,读完Daemons这个类的源代码,解决方法就出来了。当然也不止老师的实现这一种方案,还有其他的点来绕过这个机制。个人觉得这个bug的修复重点不在怎么绕过,而是绕过之后到底会不会产生其他影响。
    
     3
  • 董晓航
    2018-12-14
    能给一下toast动态代理TN的demo吗?大神
    
     3
  • 、、cryAllen
    2018-12-07
    由于从事的工作内容涉及到底层Framwork比较多,目前日常工作中也是经常需要分析BUG,那么分析的素材自然就是log文件,整个Android 系统真的是很好旁观者,我们一切的操作行为基本都是有记录的。如果碰到崩溃的问题,我自己基本解决思路则是先在全局log中搜索是否有Die关键字,然后看进程号,进程号是否有重启过,然后去system_app_crash@1451577628472.txt看相关错误,很多都是java.lang.RuntimeException异常居多。
    
     3
  • 信仰年轻
    2018-12-15
    发现一个好工具 腾讯GT
    
     2
  • Z
    2018-12-05
    学习了,最近也在学习linux 内核,很强大,作为一个一年的菜鸟受益匪浅,推荐大伙可以看看
    
     2
  • jason
    2018-12-04
    TimeoutException 直接调用stop存在什么安全问题?请大神指教一二。

    作者回复: Stop的时候有一定概率导致即使没有超时也会报timeoutexception

    
     2
  • Geek_f342a0
    2019-10-09
    崩溃主要分为java层crash,c/c++层crash,anr导致的crash
    1.java层crash:可以通过手机logcat日志分析,也可以继承UncaughtExceptionHandler,并通过Thread.setDefaultUncaughtExceptionHandler来处理系统的异常,基本能收集到所有java层的crash的问题。
    2.c/c++层的crash:通过logcat日志进行分析,也可以通过breakpad的来收集dump,分析dump文件,如果是内存堆或者栈出问题,可能收集不了任何堆栈,这要通过别的手段进行分析,通过分析代码,或者增加一些内存分配的判断,或者增加日志来解决。
    3.anr的crash:通过logcat日志分析,anr的日志也可以通过/data/anr/traces.txt进行分析,分析整个的堆栈,同时也要检查代码有没有处理耗时的操作,比如在主线程,或者广播处理或者Service处理是否会超时了。
    展开
    
     1
  • Wilson
    2019-06-05
    pthread_create (1040KB stack) failed: Out of memory老师这个有没有好的解决方法?

    作者回复: 可以把线程和句柄 dump出来,看看是哪里出了问题

    
     1
  • Geek_Yasin28
    2019-03-14
    请问有没有native崩溃后成功获取java堆栈的例子, 是只能用hook libart.so实现吗?
    这边参考实现了native崩溃获取, 但是在native崩溃时, 信号处理函数去唤醒之前等待的线程,去回调java或者抛出异常给java处理都没有反应。

    作者回复: 一般情况下直接jni调用也是可以拿到的,除了一些特殊情况

    
     1
我们在线,来聊聊吧