Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

Application of bytecode technology in module dependency analysis

2025-02-25 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Internet Technology >

Share

Shulou(Shulou.com)06/03 Report--

Background

In recent years, with the rapid development of mobile phone business, in order to meet the demands of mobile users and the rapid growth of business functions, the technical architecture of mobile terminal has gradually developed from a single large-scale engineering application to modularization and componentization. Take Amap as an example, the code on the Android side has broken through the million-line level, and more than 100 modules have participated in the final construction.

Just imagine, without a standard set of dependent detection and monitoring tools, it won't be long before the dependency of the module may turn into a mess.

From the perspective of module Owner, why is dependency analysis so important?

As a module Owner, I first want to know "who depends on me and which interfaces I rely on". Only in this way can we evaluate the scope of impact of the changes in this module and the reasonableness of the exposed interfaces.

I also want to know, "who do I rely on? which external interfaces have been called" and have a good idea of the external capabilities needed.

From a global perspective, a healthy dependency structure should not only prevent the "lower-level module" from directly relying on the "upper-level module", but also put an end to circular dependence. By analyzing the overall dependency relationship, we can quickly locate unreasonable dependencies and expose business problems in advance.

Therefore, dependency analysis is a very important part of the R & D process.

Common ways of dependency analysis

When it comes to Android dependency analysis, the first thing that comes to mind may be the following scenarios:

Analyze the Gradle dependency tree.

Scan the import declaration in the code.

Use the analysis capabilities that come with Android Studio.

Let's analyze these options one by one:

1. Gradle dependency tree

Using the command. / gradlew:: dependencies-- configuration releaseCompileClasspath-Q, you can easily get the dependency tree of the module, as shown in the figure:

It is not difficult to see that there are two problems with this approach:

A declaration is a dependency, and even if there are no libraries used in the code, it will be output to the result.

It can only be parsed to the module level, not accurate to the method level.

two。 Scan import statement

Scan the import statement in the Java file to get the invocation relationship between files (classes).

Because the correspondence between modules and files (classes) is very easy to get (scan directories). Therefore, the dependency relationship between files (classes) is obtained, that is, the file (class) level dependency relationship between modules is obtained.

Compared with Gradle dependency scanning, this scheme improves the result dimension and can be analyzed to the file (class) level. But it also has some disadvantages:

Unable to handle the import * situation.

Scanning scenarios that have import but do not use corresponding classes is too inefficient (source string lookups are required).

3. Use the analysis capabilities that come with IDE

Trigger the Android Studio menu "Analyze"-> "Analyze Dependencies" to get method-level dependency data between modules. As shown in the figure:

Android Studio can accurately analyze the "method-level" reference relationship between modules, support jump view in IDE, and scan references to Android SDK.

This scheme is better than the previous two, mainly accurate. But it also has several problems:

It takes a long time: it takes about 10 minutes to fully analyze the full source code of AMap.

The analysis results can not be reused by third parties and can not generate a visual dependency graph.

To analyze forward and reverse dependencies, you need to scan twice.

Summarize the above three solutions: Gralde dependency is based on project configuration, the granularity is too coarse and the result is not accurate. "Import scanning scheme" can get file-level dependence but incomplete data. Although the result of IDE scan is accurate, it is difficult to reuse data and is not convenient for engineering.

Why use bytecode for analysis?

Referring to the Android build flow chart, all Java source code and R.java files generated by aapt will be compiled into .class files, then compiled into dex files, and finally generated into apk files through apkbuilder. The .class file in the figure is what we call Java bytecode, which is a binary escape of Java source code.

On Android, common bytecode application scenarios include:

Bytecode stub: used to monitor the performance of UI, memory, network and other modules.

Modify the jar package: for passive libraries, edit the bytecode to achieve some simple logical modifications.

Going back to the topic of this article, why analyze bytecode instead of Java code or dex files?

We don't use Java code because some libraries are provided in jar or aar, and we can't get the source code. The dex file is not used because it does not have a useful parsing tool. So parsing bytecode is almost our only option.

How do I use bytecode to analyze dependencies?

To get the dependency between modules is to get the dependency between "classes between modules". To determine the relationship between classes, you can analyze the statements of class bytecode.

1. When will you analyze it?

Students who understand the construction process of Android should be familiar with the task of transform. It is a bytecode Hook entry provided by the Android Gradle plug-in.

In the transform task, all bytecode files (including tripartite libraries) are entered in Input format.

Take JarInput as an example, analyze its file field and get the name of the module. Parsing the file file, you can get all the bytecode files of this module.

With the module name and the class file under the corresponding path, the correspondence between the module and the class is established, which is the first key data we get.

two。 What tools do you use for analysis?

Tools for parsing Java bytecode, the most commonly used include Javassit,ASM,CGLib. ASM is a lightweight class library with good performance, but requires direct manipulation of JVM instructions. CGLib is an encapsulation of ASM, providing a more advanced interface.

Javassist, by contrast, is much simpler. It is based on Java's API and does not need to manipulate JVM instructions, but its performance is lower (because Javassit adds a layer of abstraction). In the engineering prototype stage, in order to quickly verify the results, we give priority to Javassit.

3. What is the specific plan?

Let's first look at a simple example of how to analyze the invocation relationship of the following code:

1: package com.account;2: import com.account.B;3: public class A {4: void methodA () {5: BB = new B (); / / initializes the instance b6: b.methodB () of Class B; / / calls b's methodB method 7:} 8:}

Step 1: initialize the environment, load the bytecode A.class, and register the statement parser.

/ / initialize ClassPool and register the bytecode file directory with Pool. ClassPool pool = ClassPool.getDefault (); pool.insertClassPath ('') / / load class ACtClass cls = pool.get ("com.account.A"); / / register expression parser to class AMyExprEditor editor = new MyExprEditor (ctCls) ctCls.instrument (editor)

Step 2: customize the expression parser and analyze class A (take parsing statement calls as an example).

Class MyExprEditor extends ExprEditor {@ Override void edit (MethodCall m) {/ / the name of the class in which the statement is called def clsAName = ctCls.name / / the method in which the statement is called def where = m.where () .methodInfo.getName () / / the line on which the statement is called def line = m.lineNumber / / the name of the called class Def clsBName = m.className / / the called method def methodBName = m.methodName} / / omits other parsing functions.}

ExprEditor's edit (MethodCall m) callback intercepts all method calls (MethodCall) in Class A.

In addition to parsing MethodCall in this example, it also supports parsing new,new Array,ConstructorCall,FieldAccess,InstanceOf, casting, and try-catch statements.

After parsing Class A, we get the dependence information of An on B:

Class1Class2Exprmethod1method2lineNocom.account.Acom.account.BNewExprmethodA5com.account.Acom.account.BmethodCallmethodAmethodB6

The simple explanation is as follows:

Line 5 of the class com.account.A (within the methodA method), calling the constructor of com.account.B

Line 6 of the class com.account.A (within the methodA method), calling the methodB function of com.account.B

This is the method-level dependency data between classes. Combined with the corresponding relationship between "modules and classes" obtained in step 1, we finally get the "method-level dependency data between modules".

Based on these basic data, we can also customize dependency detection rules and generate global module dependency graph, which will not be expanded in this paper.

Summary

This paper mainly introduces the importance of module dependency analysis in the process of research and development, and analyzes the common dependency analysis schemes of Android, from Gradle dependency tree analysis, Import scanning, using IDE analysis, to the final bytecode parsing. The closer the solution is to the source, the more fundamental the solution is.

Pay attention to Gaode technology and find more professional content in the field of travel technology.

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Internet Technology

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report