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的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被改成了如下
DexExecTask的Rundx被改成了如下
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被改成了
结论
ANT_DEX_EXEC_TASK 这个任务,就没做什么核心的事情,它做的主要的事情是,
- 检测依赖的jar包是否有我们指定的jar包的名字
- 在rundex的时候,设置instrumentation是否可用
另外取消所有有关ANT_DEX_EXEC_TASK的任务,对打包以及插码没有任何影响