Method and system for dynamically processing resource id based on bytecode instrumentation, and medium

By using bytecode instrumentation to build a resource ID mapping table in Android applications and replacing the GETSTATIC instruction with a dynamic resolution method, the problem of inconsistent resource IDs under multi-channel packaging is solved, achieving efficient resource ID acquisition and performance improvement.

CN123030224APending Publication Date: 2026-11-03SUZHOU JIUGONG DIGITAL TECH CO LTD
View PDF 2 Cites 0 Cited by

Patent Information

Application Number
CN202611528875.8
Authority / Receiving Office
CN · China
Patent Type
Applications(China)
Current Assignee / Owner
Filing Date
2026-09-30
Publication Date
2026-11-03

AI Technical Summary

Technical Problem

In Android application development, resource IDs may be inconsistent across different channels in multi-channel packaging scenarios, leading to resource reference errors and performance loss. Existing technologies require manual maintenance of resource names or rely on manual annotation, which cannot achieve efficient and non-intrusive dynamic resolution of resource IDs.

Method used

By using bytecode instrumentation, a mapping table of resource types, names and IDs is built during the compilation phase, replacing the GETSTATIC instruction with a dynamic resource ID resolution method. The Gradle compilation process is used to automatically handle static field references of R classes, and a memory cache is built at runtime for O(1) lookup.

Benefits of technology

It enables efficient automatic conversion of resource IDs without changing developers' coding habits, improves resource ID acquisition performance by 5-20 times, solves resource ID conflict problems, and improves development efficiency and runtime performance.

✦ Generated by Eureka AI based on patent content.

Smart Images

  • Figure CN123030224A_ABST
    Figure CN123030224A_ABST
Patent Text Reader

Abstract

The application discloses a resource ID dynamic processing method based on bytecode plug-in, which registers a bytecode conversion task after Java source code is compiled into a class file and before Dex compilation in an Android compilation process; a mapping table of resource types, resource names and resource IDs is constructed and outputted when the task is executed; a class file is traversed, and a bytecode operation framework is used to identify a target file containing an R class static field GETSTATIC instruction; a replacement instruction sequence is generated for an instruction meeting a condition, a dynamic resource ID analysis method is called and corresponding resource types and names are carried; and a memory cache is constructed based on the mapping table or reflection at runtime, resource IDs are found and returned by taking the resource types and names as keys; the application realizes zero-code-invasive resource ID dynamic analysis, and reduces the runtime search complexity to O(1).
Need to check novelty before this filing date? Find Prior Art

Description

Technical Field

[0001] This invention relates to the field of mobile application development technology, and in particular to a method, system and medium for dynamic processing of resource IDs based on bytecode instrumentation. Background Technology

[0002] In Android application development, multi-channel packaging is a fundamental technology for application distribution and operational data statistics. Developers use Gradle productFlavors to build independent channel packages for different app stores (such as Huawei AppGallery, Xiaomi App Store, Tencent App Store, etc.). During this process, resources such as layouts, images, and strings in the application are statically referenced through R classes automatically generated during AAPT / AAPT2 compilation, and each resource is assigned a unique integer resource ID (e.g., R.layout.activity_main = 0x7f030012).

[0003] However, when a project has multiple channels and each channel contains different resources, the same resource name may be assigned different resource ID values ​​in the compilation artifacts of different channels. The reference to the static field of class R in the code is fixed as a constant integer value after compilation (corresponding to the GETSTATIC instruction in the Java Virtual Machine bytecode). This may cause the constant resource ID to point to the wrong resource in the current channel when dynamically loading modules, in plug-in scenarios, or when accessing resources across channels. It may even cause a ResourceNotFoundException exception because the ID does not exist in the current resource table.

[0004] To address the above issues, a common solution in existing technologies is to require developers to abandon the direct referencing of R.xxx during the coding phase and instead use the Resources.getIdentifier(resourceName, resourceType, packageName) method to dynamically look up the resource ID at runtime using the resource name string. While this approach can solve the problem of fixed resource IDs, it has the following issues: (1) Developers need to manually maintain the resource name string and cannot enjoy the convenience of IDE's code auto-completion, refactoring, and compile-time checks; (2) The getIdentifier() method internally performs string matching by traversing the resource table, with a time complexity of O(n), which results in significant performance overhead in scenarios with frequent calls; (3) The resource name is hard-coded in the form of a string literal, and cannot be automatically updated when the resource is renamed, which can easily lead to a runtime ResourceNotFoundException.

[0005] Furthermore, bytecode instrumentation technology has been attempted for code replacement during the Android compile-time. For example, Chinese patent CN116991504B discloses a method for dynamically loading and updating multiple resources in an Android app. This method uses GradleTransform and a bytecode manipulation framework (such as ASM) to replace System.loadLibrary and System.loadAPI function calls in third-party libraries with custom functions during compile-time, thereby achieving dynamic loading of .so libraries. This solution handles the replacement of method call instructions (INVOKESTATIC), which operates on system API calls and does not involve the identification and replacement of R-class resource ID field references (GETSTATIC instructions).

[0006] For example, Chinese patent application CN113918212A discloses a method and apparatus for click debouncing based on ASM bytecode instrumentation, which inserts debouncing logic code into click components marked with debouncing during the compilation stage. This solution has the following limitations: (1) It relies on developers to manually add debouncing annotations in the code, which still requires modification of coding habits; (2) It only instrumentes specific types of click event handling methods (OnClickListener), and does not involve the processing of R-class static fields (GETSTATIC directives); (3) The instrumentation targets rely on manual annotation and do not have the ability to automatically identify and cover all R-class reference scenarios.

[0007] It is evident that while existing bytecode instrumentation solutions have achieved compile-time code replacement, they share the following common shortcomings: (1) None of them involve the identification and replacement of R-class static field references (GETSTATIC directive); (2) Existing solutions are mostly customized for specific scenarios (SO loading, click debouncing), lacking coverage of the general scenario of R-class resource references; (3) Some solutions still require developers to modify their coding habits (such as adding annotations), failing to achieve true zero intrusion. In addition, existing solutions do not provide a preloading mechanism for resource mapping tables, making it impossible to achieve O(1) level runtime resource ID lookup.

[0008] Therefore, there is an urgent need for a solution that can automatically convert static field references of R classes into high-performance dynamic resource IDs during the compilation phase without changing the developer's coding habits or requiring any code annotations. Summary of the Invention

[0009] The purpose of this invention is to provide a method, system, and medium for dynamic processing of resource IDs based on bytecode instrumentation, thereby solving all or one of the aforementioned problems in the prior art.

[0010] To solve the above-mentioned technical problems, the specific technical solution of the present invention is as follows:

[0011] On the one hand, the present invention provides a resource ID dynamic processing method based on bytecode instrumentation, which is applied to the Gradle compilation process of Android projects. The Gradle compilation process includes a compilation stage that compiles Java source code into class files and a conversion stage that converts class files into Dex files, including the following steps: after the compilation stage and before the conversion stage, registering a bytecode conversion task;

[0012] When performing the bytecode conversion task, a mapping table corresponding to the resource type, resource name, and resource ID is constructed and the mapping table is output.

[0013] Iterate through the class files output by the compilation phase and use the bytecode manipulation framework to identify target class files containing GETSTATIC instructions for static fields of R classes;

[0014] For the GETSTATIC instruction in the target class file that meets the preset conditions, a replacement instruction sequence containing a constant loading instruction and a static method calling instruction is generated to replace the GETSTATIC instruction. The converted class bytecode is output. The replacement instruction sequence is used to call the dynamic resource ID parsing method and carries the resource type and resource name corresponding to the replaced GETSTATIC instruction.

[0015] During the application runtime phase, based on the mapping table or by reading the mapping relationship data obtained by the current R class through reflection, a resource mapping cache in memory is constructed. In response to a resource ID parsing request, the corresponding resource ID is searched and returned in the resource mapping cache using the resource type and resource name as keys.

[0016] As an improved solution, the mapping table corresponding to the resource type, resource name, and resource ID includes:

[0017] Gradle's compiler variant awareness mechanism is used to obtain the channel information of the current compilation and determine the full path of the R class for the corresponding channel.

[0018] Parse the source code of the R class or the R.class file of the current channel, traverse all inner classes of the R class, and extract all static integer fields declared in each inner class;

[0019] A two-level hash mapping table is constructed using the name of the inner class as the resource type, the name of the static integer field as the resource name, and the value of the static integer field as the resource ID. The first level uses the resource type as the key and the corresponding value is the second level hash table, and the second level uses the resource name as the key and the corresponding value is the resource ID.

[0020] As an improved solution, the preset conditions include:

[0021] The class of the field in the GETSTATIC instruction matches the inner class of the R class under the target R class package name, and the target R class package name is pre-configured in the bytecode conversion task;

[0022] The field descriptor for the GETSTATIC command is I;

[0023] The package name of the class containing the GETSTATIC instruction is not in the preset list of excluded package names.

[0024] As an improved approach, the resource type and resource name carried in the replacement instruction sequence are extracted in the following manner:

[0025] When the field of the GETSTATIC directive belongs to an inner class of class R, and the class name matches {packageName}.R$ <resourcetype>In the mode, the part after the last $ symbol in the inner class name is taken and converted to lowercase, which is used as the resource type, and the field name of the GETSTATIC instruction is used as the resource name;

[0026] When the class of the field in the GETSTATIC instruction is the R class itself, that is, when the class name exactly matches {packageName}.R, the GETSTATIC instruction is skipped and no conversion is performed.

[0027] As an improved approach, generating a replacement instruction sequence containing a load constant instruction and a call static method instruction to replace the GETSTATIC instruction includes:

[0028] The first load constant instruction, the second load constant instruction, the third load constant instruction, and the static method call instruction are generated sequentially.

[0029] The first constant loading instruction pushes the resource type as a string constant onto the top of the operand stack;

[0030] The second constant loading instruction pushes the resource name as a string constant onto the top of the operand stack;

[0031] The third constant loading instruction pushes the current application's package name string onto the top of the operand stack;

[0032] The instruction to call a static method invokes the static method `resolveResourceId` of the dynamic resource ID resolution method. The signature of the static method is `(Ljava / lang / String;Ljava / lang / String;Ljava / lang / String;)I`.

[0033] Instead of passing the GETSTATIC instruction, the first load constant instruction, the second load constant instruction, the third load constant instruction, and the static method call instruction are output sequentially.

[0034] As an improved approach, an incremental compilation step is also included:

[0035] During the first full compilation, a content fingerprint is calculated for each bytecode-converted class file, the converted class bytecode is stored in a cache subdirectory, and the correspondence between the content fingerprint and the cache file path is recorded in an index file;

[0036] During subsequent incremental compilation, the index file is read, and the content fingerprint of the current class file is compared with the fingerprint recorded in the index file. If they match, the previously converted class bytecode is read from the cache subdirectory as output. If they do not match or there is no record in the index file, the identification and replacement steps are performed on the class file, and the cache subdirectory and the index file are updated.

[0037] As an improved approach, the construction of an in-memory resource mapping cache is specifically implemented through one of the following methods:

[0038] Method 1: During the execution of the Application.onCreate method of the application, the R class that has been loaded in the current process is read through the Java reflection mechanism, all inner classes of the R class and their declared static integer fields are traversed, and the resource mapping cache in memory is constructed.

[0039] Method 2: Load the mapping table directly during the application startup phase to build the resource mapping cache in memory.

[0040] As an improved approach, the step of searching for and returning the corresponding resource ID in the resource mapping cache using the resource type and resource name as keys includes:

[0041] Using the resource type as the first-level key and the resource name as the second-level key, a search is performed in the resource mapping cache;

[0042] If the search finds a match, the corresponding resource ID is returned directly.

[0043] If the search fails, the Android system's Resources.getIdentifier(name, type, packageName) method is called to perform a reflection search, and the search result is returned. At the same time, the found resource ID is stored in the resource mapping cache with the resource type and the resource name as keys.

[0044] On the other hand, the present invention also provides a resource ID dynamic processing system based on bytecode instrumentation, applied in the Gradle compilation process of Android projects. The Gradle compilation process includes a compilation stage that compiles Java source code into class files and a conversion stage that converts class files into Dex files. The system is characterized by including:

[0045] A build tool integration module is used to register bytecode conversion tasks after the compilation phase and before the conversion phase;

[0046] The resource mapping table construction module is used to construct a mapping table corresponding to the resource type, resource name and resource ID when performing the bytecode conversion task, and output the mapping table.

[0047] The class file scanning module is used to traverse the class files output by the compilation stage and use the bytecode manipulation framework to identify target class files containing GETSTATIC instructions for static fields of R classes;

[0048] The bytecode conversion module is used to generate a replacement instruction sequence for GETSTATIC instructions in the target class file that meet preset conditions, to replace the GETSTATIC instructions, and output the converted class bytecode. The replacement instruction sequence is used to call the dynamic resource ID parsing method and carries the resource type and resource name corresponding to the replaced GETSTATIC instruction.

[0049] The dynamic resource ID parsing module is used during application runtime to construct an in-memory resource mapping cache based on the mapping table or by reading the mapping relationship data obtained by the current R class through reflection. In response to a resource ID parsing request, it searches for and returns the corresponding resource ID in the resource mapping cache using the resource type and resource name as keys.

[0050] On the other hand, the present invention also provides a computer-readable storage medium storing a computer program, wherein the computer program, when executed by a processor, implements the steps of the bytecode instrumentation-based resource ID dynamic processing method.

[0051] The beneficial effects of the technical solution of this invention are:

[0052] 1. The resource ID dynamic processing method based on bytecode instrumentation described in this invention can automatically complete the bytecode-level conversion of R-class resource ID references during the Android application compilation stage without changing the developer's coding habits. It effectively solves the resource ID conflict problem in multi-channel packaging scenarios and improves the resource ID acquisition performance by 5-20 times. It makes up for the shortcomings of existing technologies that require manual switching to getIdentifier(), have poor runtime performance, and cannot enjoy the convenience of IDEs. It has high application value.

[0053] 2. The resource ID dynamic processing system based on bytecode instrumentation described in this invention can realize the resource ID dynamic processing method based on bytecode instrumentation described in this invention through the cooperation of system modules.

[0054] 3. The computer-readable storage medium of the present invention can store computer software instructions for implementing the method of the present invention, guide the cooperation of various modules of the system, and thereby realize the resource ID dynamic processing method based on bytecode instrumentation of the present invention. The computer-readable storage medium of the present invention effectively improves the operability and deployment convenience of the method. Attached Figure Description

[0055] To more clearly illustrate the specific embodiments of the present invention or the technical solutions in the prior art, the drawings used in the description of the specific embodiments or the prior art will be briefly introduced below. Obviously, the drawings described below are some embodiments of the present invention. For those skilled in the art, other drawings can be obtained from these drawings without creative effort.

[0056] Figure 1 This is a block diagram of the overall system architecture of an embodiment of the present invention;

[0057] Figure 2 These are comparison images of bytecode conversion before and after in an embodiment of the present invention;

[0058] Figure 3 This is a diagram showing the insertion position of an embodiment of the present invention in the Gradle compilation process;

[0059] Figure 4 This is a flowchart illustrating the process of constructing and searching the resource mapping table during runtime in an embodiment of the present invention.

[0060] Figure 5 This is a diagram illustrating the effect of multi-channel differentiated resource analysis in an embodiment of the present invention. Detailed Implementation

[0061] The preferred embodiments of the present invention will now be described in detail with reference to the accompanying drawings, so that the advantages and features of the present invention can be more easily understood by those skilled in the art, thereby providing a clearer and more explicit definition of the scope of protection of the present invention.

[0062] In the description of this invention, it should be noted that the embodiments described in this invention are only some embodiments of this invention, not all embodiments; based on the embodiments of this invention, all other embodiments obtained by those skilled in the art without creative effort are within the scope of protection of this invention.

[0063] The terms "first," "second," etc., used in this specification, claims, and the accompanying drawings are used to distinguish similar objects and are not necessarily used to describe a specific order or sequence. It should be understood that such data can be interchanged where appropriate so that the embodiments described herein can be implemented in orders other than those illustrated or described herein. Furthermore, the terms "comprising" and "having," and any variations thereof, are intended to cover a non-exclusive inclusion; for example, a process, method, apparatus, product, or device that comprises a series of steps or units is not necessarily limited to those steps or units explicitly listed, but may include other steps or units not explicitly listed or inherent to such processes, methods, products, or devices.

[0064] In the description of this invention, it should be noted that:

[0065] Bytecode manipulation frameworks refer to software development frameworks or libraries that have the ability to read, parse, modify, and output class files, including but not limited to ASM, Javassist, ByteBuddy, etc. They provide application programming interfaces (APIs) for traversing the class file structure and accessing and modifying bytecode instructions within methods.

[0066] ASM is a Java bytecode manipulation and analysis framework that provides core APIs such as ClassReader, ClassVisitor, ClassWriter, and MethodVisitor, enabling the reading, parsing, modification, and output of compiled class files.

[0067] Bytecode instrumentation refers to the technique of inserting, modifying, or replacing instruction sequences at the bytecode level of a compiled class file, thereby changing the program's runtime behavior without modifying the source code.

[0068] Resource ID is a unique integer identifier assigned by the Android system at compile time to each resource file (including layout files, images, strings, colors, sizes, styles, ID identifiers, etc.). In the R class, it is declared as a public static final int field.

[0069] The R class is a Java class automatically generated by the Android build toolchain (AAPT / AAPT2) based on the resource files in the project. It contains several inner classes (such as R.layout, R.string, R.drawable, R.id, R.color, etc.), and the static integer field in each inner class corresponds to the ID value of a specific resource.

[0070] Multi-channel packaging refers to the process of generating APK or AAB installation packages with different channel identifiers and differentiated resource configurations for different app stores (such as Huawei App Market, Xiaomi App Store, Tencent App Store, etc.) based on the same set of source code, through Gradle productFlavors or other channel sub-packaging solutions (such as Meituan Wallet).

[0071] The GETSTATIC instruction is an instruction (Opcode: 0xB2) in the Java Virtual Machine bytecode instruction set. It is used to retrieve the value of a specified static field of a specified class and push it onto the operand stack. In the Android R class resource reference scenario, this instruction is used to retrieve the static integer resource ID value in the inner class of R class.

[0072] The LDC instruction is an instruction (Opcode: 0x12) in the Java Virtual Machine bytecode instruction set, used to push constants (including string constants, integer constants, floating-point constants, etc.) from the constant pool onto the top of the operand stack;

[0073] The INVOKESTATIC instruction is an instruction (Opcode: 0xB8) in the Java Virtual Machine bytecode instruction set. It is used to call a static method of a specified class, execute the method, and push the return value (if any) onto the operand stack.

[0074] The Transform API is an application programming interface provided by the Android Gradle Plugin (AGP) in versions below 4.0 for intercepting and transforming class files before they are converted to dex files during the compilation process.

[0075] CompilationTask is an application programming interface provided by Android Gradle Plugin (AGP) in versions 4.0 and above. It is used to register callback hooks after the Java compilation task is completed and can achieve class file interception and transformation functions equivalent to the Transform API.

[0076] Compilation variants are build targets in the Android Gradle build system that combine build types (such as debug and release) and product flavors (such as Huawei, Xiaomi, and Oppo). Each variant has its own independent R class and resource set.

[0077] A two-level hash table is a data structure where the first level uses resource type strings (such as "layout", "string", "drawable") as keys and the corresponding values ​​are hashed in the second level; the second level uses resource name strings (such as "activity_main", "app_name") as keys and the corresponding values ​​are integer values ​​of resource IDs. This structure supports resource ID lookup with O(1) time complexity.

[0078] The dynamic resource ID resolver, a utility class provided in this invention, contains the static method `resolveResourceId(String type, String name, String packageName)`, which is responsible for searching and returning the corresponding resource ID integer value from a preloaded two-level hash map based on the passed resource type string, resource name string, and package name string. The package name string is used to call the Android system's `Resources.getIdentifier(name, type, packageName)` method during downgrade lookup, and to locate the current application's `R` class when constructing the resource map table using reflection.

[0079] Content fingerprinting refers to a fixed-length digest value calculated from the content of a class file using a hash algorithm (such as MD5, SHA-1, etc.). It is used to uniquely identify the content state of the file at a specific time to determine whether the file has changed between two compilations.

[0080] Example 1 provides a bytecode instrumentation-based method for dynamically processing resource IDs. This method addresses the issue of different resource ID values ​​for the same resource name in different channels due to independent compilation of R classes in multi-channel packaging scenarios for Android applications. Existing technologies using the getIdentifier() string matching method suffer from low development efficiency, poor runtime performance (time complexity O(n)), error susceptibility, and poor code readability. Furthermore, existing bytecode solutions have incomplete coverage and require modifications to coding practices. Figures 1-5 As shown, it includes:

[0081] It should be noted that in steps S300 to S400 of the method of the present invention, all operations involving reading, parsing, identifying, modifying, and outputting the bytecode of the class file are implemented based on a bytecode manipulation framework. The bytecode manipulation framework includes, but is not limited to, frameworks known in the art such as ASM, Javassist, and ByteBuddy that possess class file manipulation capabilities. For ease of understanding and implementation, the following embodiments use the ASM framework (version 9.0 and above) as a preferred implementation. However, the present invention is not limited thereto, and those skilled in the art can choose any bytecode manipulation framework with corresponding capabilities to replace the implementation according to actual needs, all of which fall within the protection scope of the present invention.

[0082] The S100 and Gradle compilation process integration steps include:

[0083] S101. Add a plugin dependency declaration to the build.gradle file in the root directory of the Android project. The plugin dependency declaration points to the custom Gradle plugin that contains ASM bytecode instrumentation logic.

[0084] S102. Apply the custom Gradle plugin in the build.gradle file of the application module, and set parameters through the plugin extension configuration block. The parameters include: R class package name (used to specify the full path of the target R class), exclusion package name list (used to exclude third-party libraries or system classes that do not need to be converted), and a switch to enable resource mapping preloading optimization. As a preferred embodiment, the R class package name and exclusion package name list are set through the extension configuration interface of the custom Gradle plugin. In other embodiments, they can also be pre-configured through independent configuration files, environment variables, command line parameters or system properties, or automatically deduced by the compilation task from the project package name configuration (such as the package attribute in AndroidManifest.xml). Those skilled in the art can choose a suitable configuration method according to the actual project structure, which does not affect the implementation of the core inventive concept of the present invention.

[0085] S103. The custom Gradle plugin listens to specific stages of the Android Gradle compilation process. Through the Transform API (for AGP versions below 4.0) or by registering a CompilationTask callback (for AGP 4.0 and above), it registers the bytecode transformation task at a point in the compilation process after Java source code is compiled into class files and before Dex compilation. Figure 3 As shown;

[0086] S104. Dynamic Resource ID Resolver Class Injection Step: During the compilation process, the custom Gradle plugin injects the pre-compiled class file or Java source code file containing the Dynamic Resource ID Resolver into the classpath of the current compilation task using one of the following methods:

[0087] Method 1: Pre-install the DynamicResourceResolver class file in the plugin JAR package, copy it to the compilation output directory through the Transform task's input / output mechanism, and participate in the subsequent Dex compilation and APK / AAB packaging along with the business code's class file;

[0088] Method 2: Dynamically generate the Java source file for DynamicResourceResolver during compilation and add it to the source file collection of the Java compilation task, which is then compiled into a class file by javac.

[0089] By using the above method, it is ensured that the target class referenced by the INVOKESTATIC instruction generated in step S405 always exists in the application's classpath at runtime.

[0090] It should be noted that steps S101 to S104 describe the implementation of this invention in an Android project using the Gradle build tool as an example. However, the implementation of this invention does not rely on Gradle-specific APIs, but rather on the general compilation stage characteristic of "after Java source code is compiled into class files and before the class files are converted into Dex files" in the compilation process. For Android projects using other build tools (such as Bazel, Buck, etc.), as long as the build tool provides an extended mechanism for performing bytecode transformation at this compilation stage, this invention can be implemented through a mechanism equivalent to the Gradle Transform API or CompilationTask functionality. Similarly, the configuration of the R class package name is not limited to the Gradle plugin extension interface and can be implemented through various configuration methods. The choice of specific configuration method does not constitute a necessary technical feature of this invention. Those skilled in the art can make adaptive adjustments according to specific build tools and project structures, all of which fall within the protection scope of this invention.

[0091] S200, the steps for constructing the resource mapping table include:

[0092] S201. When the bytecode conversion task is executed, the channel information of the current compilation is obtained through Gradle's build variant awareness mechanism, and the complete path of the corresponding R class (such as com.example.R, com.example.R\$layout, etc.) is determined.

[0093] S202. Parse the source code of the R class in the current channel or the compiled R.class file, traverse all inner classes of the R class (such as R.layout, R.string, R.drawable, R.id, R.color, R.dimen, R.attr, etc.), and extract the static integer fields declared in each inner class;

[0094] S203. Construct a two-level hash mapping table with the resource type string (i.e., the inner class name, such as layout, string, drawable) as the first-level key, the resource name (i.e., the field name, such as activity_main) as the second-level key, and the resource ID integer value as the value. Output the mapping table to the compilation output directory in the form of a Java source code file or a serialized data file for runtime use.

[0095] Before performing the bytecode conversion, in order to more clearly illustrate the creative contribution of this invention compared with the existing technical solutions, the three technical routes are compared from multiple dimensions such as encoding method, IDE support, runtime performance, and applicable scenario coverage, as shown in the table below.

[0096] Table 1. Multi-dimensional comparison between the present invention and existing technical solutions.

[0097] S300, target class file scanning steps, including:

[0098] S301. Obtain the directory of class files output by the Java compilation task in step S103, including the class files generated by compiling the main project source code and the class files generated by compiling all dependent modules;

[0099] S302. Traverse all .class files in the class file directory and its subdirectories. For each class file, read its bytecode content.

[0100] S303. Use the ClassReader component provided by the bytecode manipulation framework (preferably the ASM framework in this embodiment) to parse the bytecode content and determine whether the current class file contains a GETSTATIC instruction for a static field of class R: if it does not contain it, skip the file and do not process it; if it does contain it, mark the class file as the target class file and proceed to step S400.

[0101] In other implementations, if the Javassist framework is used, the same functionality can be achieved through its CtClass and corresponding code injection API. Although the specific API interfaces of different bytecode manipulation frameworks differ, their essential functions—namely, reading class files, accessing method instructions, and replacing target instructions—are exactly the same. Those skilled in the art can implement the replacement without any creative effort.

[0102] The S400 and ASM bytecode conversion steps include:

[0103] S401. For each target class file, create a ClassWriter instance of the bytecode manipulation framework (preferably the ASM framework in this embodiment) and override its visitMethod method to return a custom MethodVisitor instance.

[0104] If other bytecode manipulation frameworks such as Javassist are used, then the corresponding class pool and code transformation tools provided by the framework are created to achieve the same functionality.

[0105] S402. In the custom MethodVisitor instance, override the visitFieldInsn method to intercept all field access commands and identify GETSTATIC commands that meet all of the following conditions:

[0106] Condition A: The field's owner class matches the R class or its inner classes under the R class package name set in step S102 (including but not limited to patterns such as {packageName}.R, {packageName}.R\$layout, {packageName}.R\$string, {packageName}.R\$drawable, {packageName}.R\$id, {packageName}.R\$color, etc.), as well as the R class inner classes automatically generated under multi-channel variants (such as patterns such as {packageName}.R\$debug\$layout, etc.).

[0107] Condition B: The field descriptor is I (int type), excluding references to the Class object itself of the inner class of R class (such as the GETSTATIC directive corresponding to R.layout.class, whose field type is Ljava / lang / Class; instead of I, it has been excluded due to descriptor mismatch).

[0108] Condition C: The field access instruction is GETSTATIC, and the PUTSTATIC instruction is not processed;

[0109] Condition D: Exclude references to R class fields in classes that match the exclusion package name list set in step S102;

[0110] S403. For GETSTATIC instructions that satisfy all conditions in step S402, extract the resource type string from the class name to which the field belongs: If the class to which the field belongs is an inner class of class R (i.e., the class name matches {packageName}.R$), then... <resourcetype>If the pattern is such as com.example.R\$layout, com.example.R\$string, etc., then the part after R$ is taken and converted to lowercase (e.g., R\$layout is extracted as layout, R\$string is extracted as string) as the resource type string, and the resource name string is extracted from the field name;

[0111] If the field belongs to the class R itself (i.e., the class name exactly matches {packageName}.R, such as com.example.R, without the inner class suffix), then further judgment is made: According to the R class generation rules of the Android compilation toolchain (AAPT / AAPT2), the R class itself only serves as a container for inner classes and does not directly declare any integer resource ID fields. Therefore, such GETSTATIC instructions will not appear in the bytecode generated by normal compilation. If such a reference is actually detected, it is determined to be an invalid reference mode, and the instruction is skipped without conversion (i.e., the original GETSTATIC instruction remains unchanged). At the same time, a warning message is output in the compilation log, prompting the developer to check whether there are abnormal reflection references to R.class or deprecated uses of R class in the code.

[0112] Specifically, the mapping relationship between the inner classes of class R and the resource type strings is shown in the table below. It should be noted that the mapping relationship listed in this table only applies to the inner classes of class R (i.e., the class name format is {packageName}.R$). <resourcetype>For example, com.example.R\$layout). The R class itself (i.e., the class name exactly matches {packageName}.R, such as com.example.R, excluding inner class suffixes) does not contain any integer resource ID field and is not within the scope of this invention. During bytecode scanning, the GETSTATIC instruction of the R class itself is skipped according to the rules in step S403.

[0113] Table 2. Mapping Relationships Between R Inner Class Names and Resource Type Strings

[0114] S404. Extract the resource name string from the field name (e.g., if the field name is activity_main, then extract activity_main).

[0115] S405. Generate a replacement instruction sequence, wherein the replacement instruction sequence includes, in sequence:

[0116] First instruction: Load constant instruction (preferably LDC instruction), push the resource type string extracted in step S403 onto the top of the operand stack;

[0117] Second instruction: Load constant instruction (preferably LDC instruction), push the resource name string extracted in step S404 onto the top of the operand stack;

[0118] Third instruction: Load constant instruction (preferably LDC instruction), pushes the current application's package name string onto the operand stack;

[0119] Fourth instruction: Call static method instruction (preferably INVOKESTATIC instruction), call the resolveResourceId static method of dynamic resource ID resolution method, the signature of the static method is (Ljava / lang / String;Ljava / lang / String;Ljava / lang / String;)I, that is, it accepts resource type string, resource name string and package name string as parameters and returns an integer resource ID;

[0120] It should be noted that, at the Java Virtual Machine bytecode level, the constant loading instructions include instructions such as LDC, LDC_W, and LDC2_W that have the function of "pushing constants onto the operand stack", and the static method calling instructions include instructions such as INVOKESTATIC that have the function of "calling static methods of a class". Those skilled in the art can select the corresponding specific instructions to implement according to the actual compilation target and bytecode version.

[0121] S406. Replace the original GETSTATIC instruction with the replacement instruction sequence generated in step S405. That is, do not call super.visitFieldInsn to pass the original instruction, but call mv.visitLdcInsn twice and mv.visitMethodInsn once in sequence to output the replacement instruction sequence.

[0122] S407. Output the converted complete class bytecode using the ClassWriter.toByteArray() method, overwriting the original class file.

[0123] S500, incremental compilation optimization steps, including:

[0124] S501. During the first full compilation, calculate the content fingerprint (such as MD5 hash value) of each bytecode-converted class file, and store the converted complete class bytecode in the form of binary files in the cache subdirectory under the compilation output directory (the cache file path and the original class file path maintain a one-to-one correspondence). At the same time, record the correspondence between the content fingerprint and the cache file path in the index file.

[0125] S502. During subsequent incremental compilation, the index file is read, and the content fingerprint of the current class file is compared with the content fingerprint of the previous compilation recorded in the index: if the fingerprints match, it is determined that the class file has not changed, and the previously converted class bytecode is directly read from the cache subdirectory as the output of this compilation, skipping the rescanning and conversion process of the file; if the fingerprints do not match or there is no record in the index, the scanning and conversion process of steps S300 to S400 is executed on the class file, and the newly generated conversion result is updated to the cache subdirectory and the index file.

[0126] S503. After each compilation is completed, update the fingerprint records in the index file and the corresponding cache files to ensure that the latest fingerprints and cache data are used in the next incremental compilation.

[0127] S600, runtime dynamic resource resolution steps, including:

[0128] S601. During the application startup phase (i.e., during the execution of the Application.onCreate method), the R class already loaded in the current process (dynamically loaded by the Android system according to the current channel) is read through Java reflection. All inner classes of the R class and their declared static integer fields are traversed to construct a two-level hash mapping table from resource type string, resource name string to resource ID, and stored in memory. The complete path of the R class used when reading the R class via reflection consists of the package name string plus ".R" (e.g., com.example.app.R). Alternatively, if the resource mapping Java source file or serialized data file has been pre-generated in step S203, this file is directly loaded during the application startup phase, and the two-level hash mapping table is constructed. Figure 4 As shown;

[0129] S602. When the R.xxx reference in the application code is converted to call DynamicResourceResolver.resolveResourceId(type, name, packageName), the resolveResourceId method first uses the passed resource type string as the first key and the resource name string as the second key to perform a lookup in the double-layer hash map constructed in step S601 with an O(1) time complexity. If the lookup is successful, the corresponding resource ID integer value is returned directly without using the package name string parameter. If the lookup is unsuccessful, the process is transferred to the downgraded lookup process in step S604, where the package name string parameter is used to call the Android system's resource lookup API.

[0130] S603. If a corresponding resource ID exists in the two-layer hash mapping table, the resource ID value is returned to the caller for use by the Android Framework's resource loading interfaces (such as setContentView, findViewById, getString, getDrawable, etc.). This achieves the effect of automatically resolving the same R.xxx code reference to the actual resource ID of the current channel under different channels. Figure 5 As shown; if it does not exist, continue with the downgrade search process in step S604;

[0131] S604. If the corresponding resource ID does not exist in the two-layer hash mapping table, the Android system's Resources.getIdentifier(name, type, packageName) method is called in a fallback manner to perform a reflection lookup. The three parameters are the resource name string, resource type string, and package name string passed in by this method, respectively. The lookup result is returned to the caller, and the found resource ID is filled back into the two-layer hash mapping table (i.e., written into the second-layer hash table) using the resource type string and resource name string as keys, so that subsequent accesses to the same resource can directly hit the cache and avoid repeated fallback lookups.

[0132] To verify the performance advantages of this invention, the solution of this invention was compared with the existing getIdentifier() method under the same test environment. The test scenarios included two typical use cases: single resource ID acquisition and batch acquisition of 100 resource IDs. The test results are shown in the table below.

[0133] Table 3 Performance Comparison Data Table

[0134] In summary, with this solution, developers do not need to change their coding habits and continue to use standard syntax such as R.layout.xxx and R.string.xxx. During the compilation phase, the conversion of R class field references is automatically completed through ASM bytecode instrumentation. At runtime, high-performance resource ID parsing is achieved through O(1) hash lookup, which effectively solves the problem of resource ID conflict from multiple channels and achieves a 5-20 times performance improvement in resource ID acquisition.

[0135] In alternative embodiments, the ASM framework used in steps S300 to S400 can be entirely replaced by the Javassist framework, ByteBuddy framework, or other frameworks capable of manipulating class file bytecode. Functionally, all of these frameworks can read class files, locate and replace target instructions; the only difference lies in the API calling methods. The specific replacement methods are within the conventional skills of those skilled in the art. Therefore, any technical solution that uses a bytecode manipulation framework to perform bytecode-level replacement of R-class field references during the compilation stage is not outside the scope of protection of this invention, regardless of the specific framework used.

[0136] Example 2: This example provides a resource ID dynamic processing system based on bytecode instrumentation, such as... Figure 1 As shown, it includes:

[0137] The Gradle plugin module is used to: register bytecode conversion tasks after Java source code is compiled into class files and before Dex compilation in response to the start of the Gradle compilation process of an Android project; the Gradle plugin module provides a configuration interface for developers to set R class package names, excluded package name lists, and resource mapping preloading optimization switches; as a preferred embodiment, the configuration interface is implemented as a Gradle plugin extension configuration block; in other embodiments, the configuration interface can also be implemented as an independent configuration class, annotation, or external configuration file reader, which is parsed and applied internally by the module; in embodiments using non-Gradle build tools, this module can be implemented as an extension plugin for the build tool or a custom compilation rule, with functionality equivalent to the Gradle plugin module described in this embodiment;

[0138] The resource mapping table construction module is used to: respond to the execution of bytecode conversion tasks, obtain the channel information of the current compilation through the Gradle compilation variant awareness mechanism, determine the complete path of the R class of the corresponding channel; parse the R class source code or R.class file of the current channel, traverse all inner classes of the R class and the static integer fields declared therein; construct a two-level hash mapping table with the resource type string as the first-level key, the resource name as the second-level key, and the resource ID integer value as the value, and output the mapping table to the compilation output directory;

[0139] The class file scanning module is used to: obtain the directory of class files output by the Java compilation task, traverse all .class files in the directory and its subdirectories; for each class file, use the ClassReader of the ASM framework to parse its bytecode content, determine whether it contains a GETSTATIC instruction for a static field of class R, and mark the class file containing the instruction as the target class file;

[0140] The bytecode conversion module, implemented based on the ASM framework, is used for: creating a ClassVisitor instance for each target class file and overriding its visitMethod method to return a custom MethodVisitor instance; overriding the visitFieldInsn method in the custom MethodVisitor instance to intercept all GETSTATIC instructions; for GETSTATIC instructions that meet the following conditions: the field's class name matches the target R class package name, the field descriptor is 'I', and it is not in the excluded package name list, extracting the resource type string from the field's class name and the resource name string from the field name, generating a replacement instruction sequence containing two LDC instructions and one INVOKESTATIC instruction, replacing the original GETSTATIC instruction, and outputting the converted class file; wherein, the ClassVisitor is used to traverse the class-level structure of the class file, and the MethodVisitor is used to traverse the method-level bytecode instructions and perform GETSTATIC instruction identification and replacement;

[0141] The dynamic resource ID parsing module is used to: during the application startup phase, read the R class already loaded in the current process through Java reflection mechanism, or directly load the resource mapping data pre-generated by the resource mapping table construction module, construct a two-layer hash mapping table from resource type, resource name to resource ID and store it in memory; in response to the resource ID parsing request that has been converted into a call to the resolveResourceId method in the application code, use the passed resource type string and resource name string as keys to perform an O(1) time complexity lookup in the two-layer hash mapping table and return the corresponding resource ID integer value;

[0142] The incremental compilation cache module is used to: calculate the content fingerprint of each class file after ASM transformation during the first full compilation and store the correspondence between the fingerprint and the file path in the cache file; during subsequent incremental compilations, compare the content fingerprint of the current class file with the cache record. If the fingerprints match, skip the transformation process of the file and directly reuse the previous transformation result.

[0143] Example 3: This example provides a computer-readable storage medium, including:

[0144] The storage medium is used to store computer software instructions used to implement the bytecode instrumentation-based dynamic resource ID processing method described in Embodiment 1 above. It includes a program for executing the program set up for the bytecode instrumentation-based dynamic resource ID processing method. Specifically, the executable program can be built into the bytecode instrumentation-based dynamic resource ID processing system described in Embodiment 2. In this way, the bytecode instrumentation-based dynamic resource ID processing system can implement the bytecode instrumentation-based dynamic resource ID processing method described in Embodiment 1 by executing the built-in executable program.

[0145] Furthermore, the computer-readable storage medium in this embodiment can be any combination of one or more readable storage media, wherein the readable storage medium includes an electrical, optical, electromagnetic, infrared, or semiconductor system, apparatus, or device, or any combination thereof.

[0146] Unlike existing technologies, this application proposes a bytecode instrumentation-based method, system, and medium for dynamic processing of resource IDs. This method enables fully automatic compile-time conversion and high-performance runtime parsing of resource ID references in multi-channel packaging scenarios for Android applications. It effectively solves the problem of conflicting R-class resource IDs generated independently by each channel. At the same time, it overcomes the shortcomings of existing getIdentifier() string matching methods, such as low development efficiency, poor runtime performance (O(n) time complexity), poor code maintainability, incomplete coverage of existing bytecode solutions, and the need to modify coding habits.

[0147] This invention allows developers to continue using the R.xxx standard syntax, retain all IDE auxiliary functions, achieve O(1) lookup through a two-layer hash mapping table, and improve performance by 5-20 times; it automatically covers all scenarios such as conditional branches, anonymous inner classes, and lambda expressions, automatically adapts to differences between multiple channels, supports incremental compilation, eliminates hard-coded strings, effectively makes up for the defects of existing technologies, and has high industrial application value.

[0148] It should be understood that in the various embodiments of this document, the sequence number of each process does not imply the order of execution. The execution order of each process should be determined by its function and internal logic, and should not constitute any limitation on the implementation process of the embodiments of this document.

[0149] It should also be understood that, in the embodiments herein, the term "and / or" is merely a description of the relationship between associated objects, indicating that three relationships can exist. For example, A and / or B can represent: A existing alone, A and B existing simultaneously, and B existing alone. Additionally, the character " / " in this document generally indicates that the preceding and following associated objects have an "or" relationship.

[0150] Those skilled in the art will recognize that the units and algorithm steps of the various examples described in conjunction with the embodiments disclosed herein can be implemented in electronic hardware, computer software, or a combination of both. To clearly illustrate the interchangeability of hardware and software, the components and steps of the various examples have been generally described in terms of functionality in the foregoing description. Whether these functions are implemented in hardware or software depends on the specific application and design constraints of the technical solution. Those skilled in the art can use different methods to implement the described functions for each specific application, but such implementation should not be considered beyond the scope of this document.

[0151] Those skilled in the art will clearly understand that, for the sake of convenience and brevity, the specific working processes of the systems, devices, and units described above can be referred to the corresponding processes in the foregoing method embodiments, and will not be repeated here.

[0152] In the embodiments provided herein, it should be understood that the disclosed systems, apparatuses, and methods can be implemented in other ways. For example, the apparatus embodiments described above are merely illustrative; for instance, the division of units is only a logical functional division, and in actual implementation, there may be other division methods. For example, multiple units or components may be combined or integrated into another system, or some features may be ignored or not executed. Furthermore, the couplings or direct couplings or communication connections shown or discussed may be indirect couplings or communication connections through some interfaces, devices, or units, or they may be electrical, mechanical, or other forms of connection.

[0153] The units described as separate components may or may not be physically separate. The components shown as units may or may not be physical units; that is, they may be located in one place or distributed across multiple network units. Some or all of the units can be selected to achieve the purpose of the embodiments described herein, depending on actual needs.

[0154] Furthermore, the functional units in the various embodiments of this document can be integrated into one processing unit, or each unit can exist physically separately, or two or more units can be integrated into one unit. The integrated unit can be implemented in hardware or as a software functional unit.

[0155] If the integrated unit is implemented as a software functional unit and sold or used as an independent product, it can be stored in a computer-readable storage medium. Based on this understanding, the technical solution of this paper, in essence, or the part that contributes to the prior art, or all or part of the technical solution, can be embodied in the form of a software product. This computer software product is stored in a storage medium and includes several instructions to cause a computer device (which may be a personal computer, server, or network device, etc.) to execute all or part of the steps of the methods described in the various embodiments of this paper. The aforementioned storage medium includes various media capable of storing program code, such as USB flash drives, portable hard drives, read-only memory (ROM), random access memory (RAM), magnetic disks, or optical disks.

[0156] The above description is merely an embodiment of the present invention and does not limit the patent scope of the present invention. Any equivalent structural or procedural transformations made based on the content of the present invention's specification and drawings, or direct or indirect applications in other related technical fields, are similarly included within the patent protection scope of the present invention.< / resourcetype> < / resourcetype> < / resourcetype>

Claims

1. A method for dynamically processing resource IDs based on bytecode instrumentation, applied to the Gradle compilation process of an Android project, wherein the Gradle compilation process includes a compilation stage that compiles Java source code into class files and a conversion stage that converts class files into Dex files, characterized in that... Includes the following steps: Register the bytecode conversion task after the compilation phase and before the conversion phase. When performing the bytecode conversion task, a mapping table corresponding to the resource type, resource name, and resource ID is constructed and the mapping table is output. Iterate through the class files output by the compilation phase and use the bytecode manipulation framework to identify target class files containing GETSTATIC instructions for static fields of R classes; For the GETSTATIC instruction in the target class file that meets the preset conditions, a replacement instruction sequence containing a constant loading instruction and a static method calling instruction is generated to replace the GETSTATIC instruction. The converted class bytecode is output. The replacement instruction sequence is used to call the dynamic resource ID parsing method and carries the resource type and resource name corresponding to the replaced GETSTATIC instruction. During the application runtime phase, based on the mapping table or by reading the mapping relationship data obtained by the current R class through reflection, a resource mapping cache in memory is constructed. In response to a resource ID parsing request, the corresponding resource ID is searched and returned in the resource mapping cache using the resource type and resource name as keys.

2. The resource ID dynamic processing method based on bytecode instrumentation according to claim 1, characterized in that: The mapping table that corresponds to the resource type, resource name, and resource ID includes: Gradle's compiler variant awareness mechanism is used to obtain the channel information of the current compilation and determine the full path of the R class for the corresponding channel. Parse the source code of the R class or the R.class file of the current channel, traverse all inner classes of the R class, and extract all static integer fields declared in each inner class; A two-level hash mapping table is constructed using the name of the inner class as the resource type, the name of the static integer field as the resource name, and the value of the static integer field as the resource ID. The first level uses the resource type as the key and the corresponding value is the second level hash table, and the second level uses the resource name as the key and the corresponding value is the resource ID.

3. The resource ID dynamic processing method based on bytecode instrumentation according to claim 1, characterized in that: The preset conditions include: The class of the field in the GETSTATIC instruction matches the inner class of the R class under the target R class package name, and the target R class package name is pre-configured in the bytecode conversion task; The field descriptor for the GETSTATIC command is I; The package name of the class containing the GETSTATIC instruction is not in the preset list of excluded package names.

4. The resource ID dynamic processing method based on bytecode instrumentation according to claim 1, characterized in that: The resource type and resource name carried in the replacement instruction sequence are extracted in the following way: When the field of the GETSTATIC directive belongs to an inner class of class R, and the class name matches {packageName}.R$ <resourcetype> In the mode, the part after the last $ symbol in the inner class name is taken and converted to lowercase, which is used as the resource type, and the field name of the GETSTATIC instruction is used as the resource name;< / resourcetype> When the class of the field in the GETSTATIC instruction is the R class itself, that is, when the class name exactly matches {packageName}.R, the GETSTATIC instruction is skipped and no conversion is performed.

5. The resource ID dynamic processing method based on bytecode instrumentation according to claim 1, characterized in that: The generation of a replacement instruction sequence containing a load constant instruction and a call static method instruction to replace the GETSTATIC instruction includes: The first load constant instruction, the second load constant instruction, the third load constant instruction, and the static method call instruction are generated sequentially. The first constant loading instruction pushes the resource type as a string constant onto the top of the operand stack; The second constant loading instruction pushes the resource name as a string constant onto the top of the operand stack; The third constant loading instruction pushes the current application's package name string onto the top of the operand stack; The instruction to call a static method invokes the static method `resolveResourceId` of the dynamic resource ID resolution method, and the signature of the static method is `(Ljava / lang / String;Ljava / lang / String;Ljava / lang / String;)I`. Instead of passing the GETSTATIC instruction, the first load constant instruction, the second load constant instruction, the third load constant instruction, and the static method call instruction are output sequentially.

6. The resource ID dynamic processing method based on bytecode instrumentation according to claim 1, characterized in that: It also includes incremental compilation steps: During the first full compilation, a content fingerprint is calculated for each bytecode-converted class file, the converted class bytecode is stored in a cache subdirectory, and the correspondence between the content fingerprint and the cache file path is recorded in an index file; During subsequent incremental compilation, the index file is read, and the content fingerprint of the current class file is compared with the fingerprint recorded in the index file. If they match, the previously converted class bytecode is read from the cache subdirectory as output. If they do not match or there is no record in the index file, the identification and replacement steps are performed on the class file, and the cache subdirectory and the index file are updated.

7. The resource ID dynamic processing method based on bytecode instrumentation according to claim 1, characterized in that: The construction of the in-memory resource mapping cache is specifically implemented through one of the following methods: Method 1: During the execution of the Application.onCreate method of the application, the R class that has been loaded in the current process is read through the Java reflection mechanism, all inner classes of the R class and their declared static integer fields are traversed, and the resource mapping cache in memory is constructed. Method 2: Load the mapping table directly during the application startup phase to build the resource mapping cache in memory.

8. The resource ID dynamic processing method based on bytecode instrumentation according to claim 1, characterized in that: The step of searching for and returning the corresponding resource ID in the resource mapping cache using the resource type and resource name as keys includes: Using the resource type as the first-level key and the resource name as the second-level key, a search is performed in the resource mapping cache; If the search finds a match, the corresponding resource ID is returned directly. If the search fails, the Android system's Resources.getIdentifier(name, type, packageName) method is called to perform a reflection search, and the search result is returned. At the same time, the found resource ID is stored in the resource mapping cache with the resource type and the resource name as keys.

9. A resource ID dynamic processing system based on bytecode instrumentation, applied in the Gradle compilation process of an Android project, wherein the Gradle compilation process includes a compilation stage that compiles Java source code into class files and a conversion stage that converts class files into Dex files, characterized in that... The system includes: A build tool integration module is used to register bytecode conversion tasks after the compilation phase and before the conversion phase; The resource mapping table construction module is used to construct a mapping table corresponding to the resource type, resource name and resource ID when performing the bytecode conversion task, and output the mapping table. The class file scanning module is used to traverse the class files output by the compilation stage and use the bytecode manipulation framework to identify target class files containing GETSTATIC instructions for static fields of R classes; The bytecode conversion module is used to generate a replacement instruction sequence for GETSTATIC instructions in the target class file that meet preset conditions, to replace the GETSTATIC instructions, and output the converted class bytecode. The replacement instruction sequence is used to call the dynamic resource ID parsing method and carries the resource type and resource name corresponding to the replaced GETSTATIC instruction. The dynamic resource ID parsing module is used during application runtime to build a resource mapping cache in memory based on the mapping table or by reading the mapping relationship data obtained by the current R class through reflection. In response to a resource ID parsing request, it searches for and returns the corresponding resource ID in the resource mapping cache using the resource type and resource name as keys.

10. A computer-readable storage medium, characterized in that, The computer-readable storage medium stores a computer program, which, when executed by a processor, implements the steps of the resource ID dynamic processing method based on bytecode instrumentation as described in any one of claims 1 to 8.

Citation Information

Patent Citations

  • Method and device for realizing click anti-shake based on ASM byte code instrumentation

    CN113918212A

  • A method, device and equipment for dynamically loading and updating multiple resources of Android App

    CN116991504B