Android Matrix总结

2022-01-12  本文已影响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;
}

上一篇下一篇

猜你喜欢

热点阅读