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

ProcessBuilder的改写逻辑


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;
}
};
}

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

一步一步来实现简单安卓性能监控之ANT打包方式_第1张图片
ProcessBuilder.png

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

也就是,调用processBuilder的start每次进程开启都做了啥


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]

分析

类似这个格式: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

  • 下一行

    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]

    意思是,开启一个进程执行的命令参数是Execute后面的,也就是调用aapt命令处理资源
  • 往下

    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]

    意思是,执行dx命令来处理 my-android-agent.jar 文件,这里要注意,这里添加了一个javaagent参数哦!!!这个javaagent参数正式我们第一次启动javaagent的时候传递进来的。这里又被传到了子进程里面了。

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

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

DexExecTask改写逻辑


private static ClassAdapter createAntTaskClassAdapter(final ClassVisitor cw, final Log log) {
final Map methodVisitors = new HashMap() {
{

            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);
        }
    };
}

DexExecTask的preDexLibraries被改成了如下

一步一步来实现简单安卓性能监控之ANT打包方式_第2张图片
插码preDexLibraries

DexExecTask的Rundx被改成了如下

一步一步来实现简单安卓性能监控之ANT打包方式_第3张图片
rundx插码.png

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


private static ClassAdapter createDexerMainClassAdapter(final ClassVisitor cw, final Log log) {
return new ClassAdapterBase(log, cw, new HashMap() {
{
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);
}
};
}
});

        }
    });
}

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

一步一步来实现简单安卓性能监控之ANT打包方式_第4张图片
Paste_Image.png

结论

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

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

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

你可能感兴趣的:(一步一步来实现简单安卓性能监控之ANT打包方式)