美文网首页
一步一步来实现简单安卓性能监控之ANT打包方式

一步一步来实现简单安卓性能监控之ANT打包方式

作者: 孔祥子看天下 | 来源:发表于2017-04-13 18:03 被阅读73次

    ProcessBuilder的改写逻辑

    <pre>
    private static ClassAdapter createProcessBuilderClassAdapter(final ClassVisitor cw, final Log log) {
    return new ClassAdapter(cw) {
    @Override
    public MethodVisitor visitMethod(final int access, final String name, final String desc, final String signature, final String[] exceptions) {
    MethodVisitor mv = super.visitMethod(access, name, desc, signature, exceptions);
    if (START_METHOD_NAME.equals(name)) {
    mv = new SkipInstrumentedMethodsMethodVisitor(new BaseMethodVisitor(mv, access, name, desc) {
    @Override
    protected void onMethodEnter() {
    this.builder.loadInvocationDispatcher().loadInvocationDispatcherKey(getProxyInvocationKey(PROCESS_BUILDER_CLASS_NAME, this.methodName)).loadArray(new Runnable() {
    @Override
    public void run() {
    loadThis();
    invokeVirtual(Type.getObjectType(PROCESS_BUILDER_CLASS_NAME), new Method("command", "()Ljava/util/List;"));
    }
    }).invokeDispatcher();
    }
    });
    }
    return mv;
    }
    };
    }
    </pre>

    ProcessBuilder的start方法,被改成了如下(我格式化了)

    ProcessBuilder.png

    ProcessBuilder的start方法都被谁调用了?

    也就是,调用processBuilder的start每次进程开启都做了啥
    <pre>
    691599399962749==>Bootstrapping agent args:logfile=workspace\aaa.txt;tttt=true
    691600686737811==>Execute: [sdk\build-tools\25.0.1\aapt.exe, package, -f, -m, -0, apk, -M, workspace\bin\AndroidManifest.xml, -S, workspace\bin\res, -S, workspace\res, -I, sdk\platforms\android-19\android.jar, -J, workspace\gen, --generate-dependencies, -G, workspace\bin\proguard.txt]

    691602027570542==>Execute: [sdk\build-tools\25.0.1\dx.bat, "-Jjavaagent:test-project\target\test-agentr=logfile=workspace\aaa.txt;tttt=true", --dex, --output, workspace\bin\dexedLibs\my-android-agent-efcafcfe1a4983df70fb48bca863819c.jar, workspace\libs\my-android-agent.jar]

    691602351193570==>Bootstrapping agent args:logfile=workspace\aaa.txt;tttt=true
    691604575500820==>Execute: [sdk\build-tools\25.0.1\dx.bat, "-Jjavaagent:test-project\target\test-agentr=logfile=workspace\aaa.txt;tttt=true", --dex, --output, workspace\bin\dexedLibs\fastjson-1.1.26-android-efaf839430a0a7a8394d7d55b0c392d1.jar, workspace\libs\fastjson-1.1.26-android.jar]

    691604872029960==>Bootstrapping agent args:logfile=workspace\aaa.txt;tttt=true
    691606526309021==>Execute: [sdk\build-tools\25.0.1\dx.bat, "-Jjavaagent:test-project\target\test-agentr=logfile=workspace\aaa.txt;tttt=true", --dex, --output, workspace\bin\dexedLibs\crittercism_v4_5_4_sdkonly-7db8d0f7a9e72de80599a5cf97e7d1fd.jar, workspace\libs\crittercism_v4_5_4_sdkonly.jar]

    691606827791573==>Bootstrapping agent args:logfile=workspace\aaa.txt;tttt=true
    691608129313368==>Execute: [sdk\build-tools\25.0.1\dx.bat, "-Jjavaagent:test-project\target\test-agentr=logfile=workspace\aaa.txt;tttt=true", --dex, --output, workspace\bin\dexedLibs\locSDK_3.3-4a69856b79665c8024bbe9255dc0a123.jar, workspace\libs\locSDK_3.3.jar]

    691608414309803==>Bootstrapping agent args:logfile=workspace\aaa.txt;tttt=true
    691609530548205==>Execute: [sdk\build-tools\25.0.1\dx.bat, "-Jjavaagent:test-project\target\test-agentr=logfile=workspace\aaa.txt;tttt=true", --dex, --output, workspace\bin\classes.dex, workspace\bin\classes, workspace\bin\dexedLibs\my-android-agent-efcafcfe1a4983df70fb48bca863819c.jar, workspace\bin\dexedLibs\fastjson-1.1.26-android-efaf839430a0a7a8394d7d55b0c392d1.jar, workspace\bin\dexedLibs\crittercism_v4_5_4_sdkonly-7db8d0f7a9e72de80599a5cf97e7d1fd.jar, workspace\bin\dexedLibs\locSDK_3.3-4a69856b79665c8024bbe9255dc0a123.jar]

    691609830571207==>Bootstrapping agent args:logfile=workspace\aaa.txt;tttt=true
    691611183745961==>Execute: [sdk\build-tools\25.0.1\aapt.exe, crunch, -v, -S, workspace\res, -C, workspace\bin\res]

    691611841932449==>Execute: [sdk\build-tools\25.0.1\aapt.exe, package, --no-crunch, -f, --debug-mode, -0, apk, -M, workspace\bin\AndroidManifest.xml, -S, workspace\bin\res, -S, workspace\res, -I, sdk\platforms\android-19\android.jar, -F, workspace\bin\SplashActivity.ap_, --generate-dependencies]

    691612245238729==>Execute: [sdk\build-tools\25.0.1\zipalign.exe, -f, 4, workspace\bin\SplashActivity-debug-unaligned.apk, workspace\bin\SplashActivity-debug.apk]
    </pre>

    分析

    类似这个格式:691599399962749==>Bootstrapping agent args:logfile=workspace\aaa.txt;tttt=true ,打印的时候是一个Key-Value结构前面使用的是system.nanoTime,后面是运行参数。

    这一行的意思是:javaagent的启动参数是 logfile=workspace\aaa.txt;tttt=true ,这个是外界给javaagent传递给javaagent的参数。
    需要启动javaagent的时候这样 -javaagent:/path/to/javaagent/agent.jar=logfile=workspace\aaa.txt;tttt=true

    • 下一行
      <pre>
      691600686737811==>Execute: [sdk\build-tools\25.0.1\aapt.exe, package, -f, -m, -0, apk, -M, workspace\bin\AndroidManifest.xml, -S, workspace\bin\res, -S, workspace\res, -I, sdk\platforms\android-19\android.jar, -J, workspace\gen, --generate-dependencies, -G, workspace\bin\proguard.txt]
      </pre>
      意思是,开启一个进程执行的命令参数是Execute后面的,也就是调用aapt命令处理资源
    • 往下
      <pre>
      691602027570542==>Execute: [sdk\build-tools\25.0.1\dx.bat, "-Jjavaagent:test-project\target\test-agentr=logfile=workspace\aaa.txt;tttt=true", --dex, --output, workspace\bin\dexedLibs\my-android-agent-efcafcfe1a4983df70fb48bca863819c.jar, workspace\libs\my-android-agent.jar]
      </pre>
      意思是,执行dx命令来处理 my-android-agent.jar 文件,这里要注意,这里添加了一个javaagent参数哦!!!这个javaagent参数正式我们第一次启动javaagent的时候传递进来的。这里又被传到了子进程里面了。

    再接着的几个都是调用dx命令处理jar文件为dalvik 能识别的格式!
    最后调用aapt处理png的图片压缩,调用zipalign处理apk文件的对齐等!

    就不写了,注意,这里的每一个命令都是在单独的进程执行的!

    DexExecTask改写逻辑

    <pre>
    private static ClassAdapter createAntTaskClassAdapter(final ClassVisitor cw, final Log log) {
    final Map<Method, MethodVisitorFactory> methodVisitors = new HashMap<Method, MethodVisitorFactory>() {
    {

                put(new Method(PRE_DEX_LIBRARIES_METHOD_NAME, "(Ljava/util/List;)V"), new MethodVisitorFactory() {
                    @Override
                    public MethodVisitor create(final MethodVisitor mv, final int access, final String name, final String desc) {
                        return new BaseMethodVisitor(mv, access, name, desc) {
                            @Override
                            protected void onMethodEnter() {
                                this.builder.loadInvocationDispatcher().loadInvocationDispatcherKey(getProxyInvocationKey(ANT_DEX_EXEC_TASK, this.methodName))
                                        .loadArray(new Runnable() {
                                            @Override
                                            public void run() {
                                                loadArg(0);
                                            }
                                        }).invokeDispatcher(false);
                                this.loadThis();
                                this.swap();
                                this.putField(Type.getObjectType(ANT_DEX_EXEC_TASK), "BlueWareAgentFile", Type.getType(Object.class));
                            }
                        };
                    }
                });
                put(new Method("runDx", "(Ljava/util/Collection;Ljava/lang/String;Z)V"), new MethodVisitorFactory() {
                    @Override
                    public MethodVisitor create(final MethodVisitor mv, final int access, final String name, final String desc) {
                        return new SafeInstrumentationMethodVisitor(mv, access, name, desc) {
                            @Override
                            protected void onMethodEnter() {
                                this.builder.loadInvocationDispatcher().loadInvocationDispatcherKey(SET_INSTRUMENTATION_DISABLED_FLAG).loadArray(new Runnable() {
                                    @Override
                                    public void run() {
                                        loadThis();
                                        getField(Type.getObjectType(ANT_DEX_EXEC_TASK), "BlueWareAgentFile", Type.getType(Object.class));
                                    }
                                }).invokeDispatcher();
                            }
                        };
                    }
                });
            }
        };
        return new ClassAdapterBase(log, cw, methodVisitors) {
            @Override
            public void visitEnd() {
                super.visitEnd();
                this.visitField(2, "BlueWareAgentFile", Type.getType(Object.class).getDescriptor(), null, null);
            }
        };
    }
    

    </pre>

    DexExecTask的preDexLibraries被改成了如下

    插码preDexLibraries

    DexExecTask的Rundx被改成了如下

    rundx插码.png

    com/android/dx/command/dexer/Main的processClass的改写逻辑

    <pre>
    private static ClassAdapter createDexerMainClassAdapter(final ClassVisitor cw, final Log log) {
    return new ClassAdapterBase(log, cw, new HashMap<Method, MethodVisitorFactory>() {
    {
    put(new Method(PROCESS_CLASS_METHOD_NAME, "(Ljava/lang/String;[B)Z"), new MethodVisitorFactory() {
    @Override
    public MethodVisitor create(final MethodVisitor mv, final int access, final String name, final String desc) {
    return new BaseMethodVisitor(mv, access, name, desc) {
    @Override
    protected void onMethodEnter() {
    log.debug("Found onMethodEnter in processClass");
    final String proxyInvocationKey = getProxyInvocationKey(DEXER_MAIN_CLASS_NAME, this.methodName);
    this.builder.loadInvocationDispatcher().loadInvocationDispatcherKey(proxyInvocationKey).
    loadArgumentsArray(this.methodDesc).invokeDispatcher(false);
    this.checkCast(Type.getType(byte[].class));
    this.storeArg(1);
    }
    };
    }
    });

            }
        });
    }
    

    </pre>

    com/android/dx/command/dexer/Main的processClass被改成了

    Paste_Image.png

    结论

    ANT_DEX_EXEC_TASK 这个任务,就没做什么核心的事情,它做的主要的事情是,

    • 检测依赖的jar包是否有我们指定的jar包的名字
    • 在rundex的时候,设置instrumentation是否可用

    另外取消所有有关ANT_DEX_EXEC_TASK的任务,对打包以及插码没有任何影响

    相关文章

      网友评论

          本文标题:一步一步来实现简单安卓性能监控之ANT打包方式

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