美文网首页
Android Matrix总结

Android Matrix总结

作者: 曾大稳丶 | 来源:发表于2022-01-12 15:41 被阅读0次

    Matrix地址:https://github.com/Tencent/matrix

    matrix fps检测

    监控Choreographer的CALLBACK_INPUT,CALLBACK_ANIMATION,CALLBACK_TRAVERSAL三个阶段并且结合handler的dispath logging打印完成时间监控,计算掉帧然后上传。

    Choreographer:https://www.cnblogs.com/huansky/p/13912202.html

    matrix anr监控

    通过handler的dispath logging打印完成,start的时候 anrHandler.post 5s的延迟task来相应anr,end移除这个事件

    matrix 函数耗时记录

    通过asm插桩函数统计,每个函数对应一个id,asm编译的时候生成函数id,在方法的进和出分别调用i和o函数进行统计。采用空间换时间的方式,预先申请一个100 * 10000 约为7.6m的long数组buffer,long存储方法id,时间戳,以及出入栈信息。计算函数耗时的时候只需要记录方法开始的index以及结束的index,然后从buffer里面取出即可。

    martix 慢函数检测

    通过handler的dispath logging打印以及结合函数耗时记录,获取handler的dispath start和end中间的所有函数计算即可,超过阀值报警通知

    martix io监控

    https://github.com/Tencent/matrix/wiki/Matrix-Android-IOCanary

    主要监控内容:

    1. 主线程的文件读写操作耗时
    2. 读写的buf过小,BufferedOutputStream优化
    3. 重复读取,常用文件,加cache
    4. 句柄和游标没有关闭
    

    实现方式

    1. 通过xhook把libopenjdkjvm.so,libjavacore.so,libopenjdk.so的open,open64,read,__read_chk,write,__write_chk,close给hook,然后记录统计。主要用于统计文件读写,在close的时候触发检测逻辑。
    
    JNIEXPORT jboolean JNICALL
    Java_com_tencent_matrix_iocanary_core_IOCanaryJniBridge_doHook(JNIEnv *env, jclass type) {
        __android_log_print(ANDROID_LOG_INFO, kTag, "doHook");
    
        for (int i = 0; i < TARGET_MODULE_COUNT; ++i) {
            const char* so_name = TARGET_MODULES[i];
            __android_log_print(ANDROID_LOG_INFO, kTag, "try to hook function in %s.", so_name);
    
            void* soinfo = xhook_elf_open(so_name);
            if (!soinfo) {
                __android_log_print(ANDROID_LOG_WARN, kTag, "Failure to open %s, try next.", so_name);
                continue;
            }
    
            xhook_hook_symbol(soinfo, "open", (void*)ProxyOpen, (void**)&original_open);
            xhook_hook_symbol(soinfo, "open64", (void*)ProxyOpen64, (void**)&original_open64);
    
            bool is_libjavacore = (strstr(so_name, "libjavacore.so") != nullptr);
            if (is_libjavacore) {
                if (xhook_hook_symbol(soinfo, "read", (void*)ProxyRead, (void**)&original_read) != 0) {
                    __android_log_print(ANDROID_LOG_WARN, kTag, "doHook hook read failed, try __read_chk");
                    if (xhook_hook_symbol(soinfo, "__read_chk", (void*)ProxyReadChk, (void**)&original_read_chk) != 0) {
                        __android_log_print(ANDROID_LOG_WARN, kTag, "doHook hook failed: __read_chk");
                        xhook_elf_close(soinfo);
                        return JNI_FALSE;
                    }
                }
    
                if (xhook_hook_symbol(soinfo, "write", (void*)ProxyWrite, (void**)&original_write) != 0) {
                    __android_log_print(ANDROID_LOG_WARN, kTag, "doHook hook write failed, try __write_chk");
                    if (xhook_hook_symbol(soinfo, "__write_chk", (void*)ProxyWriteChk, (void**)&original_write_chk) != 0) {
                        __android_log_print(ANDROID_LOG_WARN, kTag, "doHook hook failed: __write_chk");
                        xhook_elf_close(soinfo);
                        return JNI_FALSE;
                    }
                }
            }
    
            xhook_hook_symbol(soinfo, "close", (void*)ProxyClose, (void**)&original_close);
    
            xhook_elf_close(soinfo);
        }
    
        __android_log_print(ANDROID_LOG_INFO, kTag, "doHook done.");
        return JNI_TRUE;
    }
    

    补充:android 10兼容处理:

    //android 10 close hook
    //https://www.cnblogs.com/seekting/p/14423095.html
    //                "libjavacore.so"
    if(xhook_register(so_name, "android_fdsan_close_with_tag",
                      (void *) proxy_android_fdsan_close_with_tag,
                      (void **) &original_android_fdsan_close_with_tag)!=0){
        LOGE( "xhook_register android_fdsan_close_with_tag %s error",so_name);
    }
    
    
    1. 通过动态代理hook CloseGuard的report函数实现句柄和游标没有关闭检测。
    private boolean tryUnHook() {
        try {
            Class<?> closeGuardCls = Class.forName("dalvik.system.CloseGuard");
            Class<?> closeGuardReporterCls = Class.forName("dalvik.system.CloseGuard$Reporter");
            Method methodSetReporter = closeGuardCls.getDeclaredMethod("setReporter", closeGuardReporterCls);
            Method methodSetEnabled = closeGuardCls.getDeclaredMethod("setEnabled", boolean.class);
    
            methodSetReporter.invoke(null, sOriginalReporter);
    
            methodSetEnabled.invoke(null, false);
            // close matrix close guard also
            MatrixCloseGuard.setEnabled(false);
    
            return true;
        } catch (Throwable e) {
            MatrixLog.e(TAG, "tryHook exp=%s", e);
        }
    
        return false;
    }
    
    

    相关文章

      网友评论

          本文标题:Android Matrix总结

          本文链接:https://www.haomeiwen.com/subject/gdmwcrtx.html