Today, let’s analyze the matrix-trace-Canary part of Matrix framework. The relevant document can be viewed in Matrix Android TraceCanary, which is the key to read the source code. It is strongly recommended to read the document first and then read the source code.
TraceCanary is a module for detecting application lag, which is subdivided into the following modules:
- StartupTracer: indicates the startup time detection module
- FrameTracer: FPS frame rate detection module
- EvilMethodTracer: Time-consuming function detection module
- AnrTracer: ANR detection module
In these modules, we rely on MethodBeat to insert piles in advance to achieve the detection effect, so before we analyze these modules, we need to analyze what MethodBeat does and how it assists the above modules to detect.
In order not to make the article boring, the four modules above will be explained with new titles. Therefore, this paper will first give a general explanation of the piling part of Matrix-Gradle-Plugin, and the details may not be analyzed, because there are too many things involved.
Take a look at the documentation for compiling the pile section:
Through a proxy task transformClassesWithDexTask during compilation, the global class files as input, using ASM tools, efficiently to scan all the class files and pile.
The staking process has several key points: 1. The staking was chosen when the compile task was executed because the ProGuard operation was completed before the compile task, meaning that the class file at the time of staking was already confused. However, pile insertion after ProGuard is selected, because if pile insertion is carried out in advance, part of the methods do not conform to the inline rules and cannot be optimized during proguard, which ultimately leads to the number of program methods cannot be reduced, thus causing the problem of too many methods.
2. In order to reduce the amount of piling and performance loss, the class method instruction set is traversed to determine whether the scanning function only contains simple instructions such as PUT/READ FIELD, and filter some default or anonymous constructors, as well as simple and time-consuming functions such as GET /set.
3. As for the interface startup time, the time between Activity#onCreate and Activity#onWindowFocusChange needs to be counted, so the implementation classes of all activities in the application need to be collected during the process of piling. The onWindowFocusChange function is overridden.
4. In order to record the function execution process conveniently and efficiently, we assign an independent ID to each pile insertion function. In the process of pile insertion, we record the function signature of pile insertion and the assigned ID, and output a mapping after the completion of pile insertion, which is used as analytical support after data submission
Analysis of the
MatrixPlugin = om.tencent. MatrixPlugin = om.tencent. MatrixPlugin = om.tencent. MatrixPlugin = om.tencent. MatrixPlugin = om.tencent. MatrixPlugin = om.gradle-plugin
implementation-class=com.tencent.matrix.plugin.MatrixPlugin
MatrixPlugin.java
The plug-in does the following: Add the extensions parameter set by apply MatrixPlugin to the sample app build.gradle. The task as the document describes transformClassesWithDexTask 3, remove unused resource files
We entered the MatrixTraceTransform. Inject look at:
MatrixTraceTransform.java
successfully inject task:transformClassesWithDexBuilderForDebug
origTransform.transform(transformInvocation);
The origTransform is transformClassesWithDexBuilderForDebug system
At this point, we can directly look at the MatrixTraceTransform task, doTransfrom is the most important method, and I’m going to go through this part, because there are too many jumps involved, and the space is very important, Fortunately, the developer of Matrix left us three step comments, and we will follow these three steps to explain:
ParseMappingTask ParseMappingTask ParseMappingTask ParseMappingTask ParseMappingTask ParseMappingTask ParseMappingTask ParseMappingTask ParseMappingTask
- Read below the output mapping. TXT file, restore confusion in front of the class and method, in MappingCollector class mObfuscatedClassMethodMap and mOriginalClassMethodMap collection
- Read the baseMethodMapFile configuration from the definition, and directly generate TraceMethod and store it in collectedMethodMap. In sample, baseMethodMapFile does not have a configuration file
Then see CollectDirectoryInputTask and CollectJarInputTask task, the two tasks mainly collected class original files and traceClassOut file, class, we all know, the original file What is a traceClassOut file? In the default configuration, a traceClassOut path is set. This configuration path points to the Output /traceClassOut path. We can open the path below sample:
2, step2
- Iterate through the class raw files collected by DirectoryInput and CollectJarInputTask, Use TraceClassAdapter to collect bytecode to insert (collectedClassExtendMap) and classes to ignore (collectedIgnoreMethodMap)
- The class confuse file (” revert “) can be used to revert a class to a file. The class confuse file (” revert “) can be used to revert a class to a file.
CollectedClassExtendMap collection of data is needed in the pile of class, the collection of data stored in the output/mapping/methodMapping below:
Step3 get the confused class set and restored class set, then get the original file and traceOut file collected in step1, and participate in the trace operation. The content is as follows:
- Iterate through the original class file and create the traceOut path file
- Pile operation is performed on the original class file, and the content of pile insertion is as follows:
- Activity of insert AppMethodBeat onWindowFocusChanged method. The getInstance (). The at method
- Methods that satisfy the class insert I/O methods at the beginning and end
- Copy the stapled class file to the traceOut path file
conclusion
Supplementary parts:
- Matrix-gradle-plugin can set blacklist. Under sample app build.gradle, you can see balckMethodList set. For package or class with blacklist set, it will not be inserted
- If you want to see code inserted after pile effect, can be directly to check the output/mapping/traceClassOut path effect, is very convenient, suggest plug pile effect plug-ins could be as matrix to do this, when the implementation effect, No longer need to look at the various jars under Transfrom or decompile apK to see if you have actually been inserted
- To be inserted a pile of function, can be directly to check the output/mapping/ignoreMethodMapping. TXT file
- Each pile function has the corresponding methodId, if you want to see the corresponding relations, can directly see the output/mapping/methodMapping. TXT file
The overall analysis is almost, but the details still need to be buckled, my ability is limited, the wrong place also hope to correct.