Cross-thread message tracking method of Android
By hooking message handling methods in the Android system, recording and splicing stack information of client and server threads, the problem of difficult stack tracing in cross-thread communication is solved, achieving low-intrusion and efficient cross-thread message tracing.
Patent Information
- Authority / Receiving Office
- CN · China
- Patent Type
- Applications(China)
- Current Assignee / Owner
- HUNAN XIAOSUAN TECH INFORMATION CO LTD
- Filing Date
- 2026-01-27
- Publication Date
- 2026-05-05
AI Technical Summary
In the existing native Android cross-thread communication framework, the server thread cannot track the Messages generated by the client thread and their call stack information, making bug tracking difficult.
By intercepting Android system message handling methods through Hook operations, the call stack information of the client thread and the Message object are recorded and associated, and then combined with the stack information of the server thread for output.
It achieves efficient, stable, and low-intrusion cross-thread message tracing, suitable for Android application development, and adapts to UI thread exception tracing, reducing performance loss.
Smart Images

Figure CN121979768A_ABST
Abstract
Description
Technical Field
[0001] This disclosure relates to the field of data processing technology, and more particularly to a cross-thread message tracing method for Android. Background Technology
[0002] Currently, in common Android application projects, the native Android cross-thread communication framework, consisting of Handler, Lopper, and Message, is frequently used for cross-thread communication. The two communicating threads are referred to as the client thread and the server thread. The client thread sends a Message to the server thread to instruct it to run a specific program. If unexpected behavior occurs in the server thread, debugging and checking the call stack are required for bug tracking. However, in this native cross-thread framework, printing the server thread's stack only displays its own stack and cannot trace the client thread's call stack up to and including the timeline before the Message is generated.
[0003] It is evident that there is an urgent need for an efficient, stable, and low-intrusion method for cross-thread message tracing in Android. Summary of the Invention
[0004] In view of this, the present disclosure provides a cross-thread message tracing method for Android, which at least partially solves some of the problems existing in the prior art.
[0005] This disclosure provides a cross-thread message tracing method for Android, including: Step 1: During process initialization, intercept native methods related to message processing in the Android system through Hook operations; Step 2: When the client thread posts a Message object to the message queue, the recording process is triggered by the hooked enqueueMessage method to obtain and save the call stack information of the client thread, and store the call stack information with the Message object. Step 3: When the server thread retrieves and processes the Message object from the message queue, the application flow is triggered through the hooked dispatchMessage method, associating the current server thread with the Message object. Step 4: In response to the request to obtain stack information, determine whether the current thread is associated with a Message object that is being processed; if so, obtain the call stack information of the client thread associated with the Message object, and concatenate it with the stack information of the current server thread before outputting it; if not, directly output the stack information of the current thread.
[0006] According to a specific implementation of an embodiment of this disclosure, step 1 specifically includes: Step 1.1: Dynamically link the system library files to obtain the symbol address of the native method to be hooked; Step 1.2: Construct a replacement function with the same signature as the original method, and call the predefined Java layer callback interface in the replacement function; Step 1.3: Replace the execution address of the native method with the address of the replacement function to complete the Hook operation.
[0007] According to a specific implementation of this disclosure, the native method to be hooked includes an enqueueMessage method for adding messages to a queue, a dispatchMessage method for distributing and processing messages, and a loopOnce method for marking the end of a single message loop.
[0008] According to a specific implementation of an embodiment of this disclosure, the step of obtaining and saving the call stack information of the client thread includes: Capture the stack trace information of the current thread; Filter stack trace information and remove framework method call records related to message tracing management; The filtered stack information is saved as a string.
[0009] According to a specific implementation of an embodiment of this disclosure, the step of associating and storing the call stack information with the Message object includes: A weak reference mapping table is used to store the association between Message objects and client thread call stack information, where the Message object is used as the key and the corresponding call stack information string is used as the value.
[0010] According to a specific implementation of an embodiment of this disclosure, the step of associating the current server thread with the Message object includes: The current server thread is associated with the Message object through a thread-local variable, wherein the thread-local variable stores a weak reference to the Message object being processed by the current thread.
[0011] According to a specific implementation of this disclosure, when the loopOnce method being hooked detects the end of a single message loop, the weak reference of the Message object stored in the thread-local variable corresponding to the current thread is set to null.
[0012] According to a specific implementation of this disclosure, the step of concatenating the stack information with the current server thread's stack information includes: Get the complete stack trace of the current server thread; Locate the call record of the message loop processing method in the stack trace information, and replace the part before the method call record with the call stack information of the client thread; The replaced client thread call stack information is concatenated with the remaining server thread call stack information in sequence to form a complete cross-thread call chain.
[0013] According to a specific implementation of this disclosure, the method further includes an initialization step: Hook operations are performed by calling the initialization function of the Native layer during the Application initialization phase and when a new process is created in an Android application.
[0014] The Android cross-thread message tracing scheme in this embodiment includes: Step 1, during process initialization, intercepting native methods related to message processing in the Android system through Hook operation; Step 2, when a client thread submits a Message object to the message queue, triggering a recording process through the hooked enqueueMessage method to obtain and save the call stack information of the client thread, and storing the call stack information associated with the Message object; Step 3, when a server thread retrieves and processes a Message object from the message queue, triggering an application process through the hooked dispatchMessage method to associate the current server thread with the Message object; Step 4, in response to a request to obtain stack information, determining whether the current thread is associated with a Message object being processed; if so, obtaining the call stack information of the client thread associated with the Message object, concatenating it with the stack information of the current server thread, and outputting it; if not, directly outputting the stack information of the current thread.
[0015] The beneficial effects of this disclosure are as follows: the solution disclosed herein can be adapted to Android application development scenarios and directly hook the point where cross-thread communication actually takes place without modifying the project source code, resulting in less performance loss; this method can be used to trace threads created from C++ or other methods, and is suitable for UI thread exception tracing during Android development; it does not care about the thread creation process, but only about the flow of messages, thus achieving efficient, stable, and low-intrusion Android cross-thread message tracing. Attached Figure Description
[0016] To more clearly illustrate the technical solutions of the embodiments of this disclosure, the accompanying drawings used in the embodiments will be briefly introduced below. Obviously, the accompanying drawings described below are only some embodiments of this disclosure. For those skilled in the art, other drawings can be obtained based on these drawings without creative effort.
[0017] Figure 1 This is a flowchart illustrating a cross-thread message tracing method for Android provided in an embodiment of this disclosure. Detailed Implementation
[0018] The embodiments of this disclosure will now be described in detail with reference to the accompanying drawings.
[0019] The following specific examples illustrate the implementation of this disclosure. Those skilled in the art can easily understand other advantages and effects of this disclosure from the content disclosed in this specification. Obviously, the described embodiments are only a part of the embodiments of this disclosure, and not all of them. This disclosure can also be implemented or applied through other different specific embodiments, and the details in this specification can also be modified or changed based on different viewpoints and applications without departing from the spirit of this disclosure. It should be noted that, in the absence of conflict, the following embodiments and features in the embodiments can be combined with each other. Based on the embodiments in this disclosure, all other embodiments obtained by those skilled in the art without creative effort are within the scope of protection of this disclosure.
[0020] It should be noted that various aspects of embodiments within the scope of the appended claims are described below. It will be apparent that the aspects described herein can be embodied in a wide variety of forms, and any particular structure and / or function described herein is merely illustrative. Based on this disclosure, those skilled in the art will understand that one aspect described herein can be implemented independently of any other aspect, and two or more of these aspects can be combined in various ways. For example, any number of aspects set forth herein can be used to implement the device and / or practice the method. Additionally, this device and / or method can be implemented using structures and / or functionalities other than one or more of the aspects set forth herein.
[0021] It should also be noted that the illustrations provided in the following embodiments are only schematic representations of the basic concept of this disclosure. The illustrations only show the components related to this disclosure and are not drawn according to the number, shape and size of the components in actual implementation. In actual implementation, the form, quantity and proportion of each component can be arbitrarily changed, and the layout of the components may also be more complex.
[0022] Furthermore, specific details are provided in the following description to facilitate a thorough understanding of the examples. However, those skilled in the art will understand that the described aspects can be practiced without these specific details.
[0023] This disclosure provides a cross-thread message tracing method for Android, which can be applied to cross-thread communication processes in Android application projects.
[0024] See Figure 1 This is a flowchart illustrating a cross-thread message tracing method for Android provided in an embodiment of this disclosure. Figure 1 As shown, the method mainly includes the following steps: Step 1: During process initialization, intercept native methods related to message processing in the Android system through Hook operations; Furthermore, step 1 specifically includes: Step 1.1: Dynamically link the system library files to obtain the symbol address of the native method to be hooked; Step 1.2: Construct a replacement function with the same signature as the original method, and call the predefined Java layer callback interface in the replacement function; Step 1.3: Replace the execution address of the native method with the address of the replacement function to complete the Hook operation.
[0025] Furthermore, the native methods to be hooked include the enqueueMessage method for adding messages to a queue, the dispatchMessage method for dispatching and processing messages, and the loopOnce method for marking the end of a single message loop.
[0026] Step 2: When the client thread posts a Message object to the message queue, the recording process is triggered by the hooked enqueueMessage method to obtain and save the call stack information of the client thread, and store the call stack information with the Message object. Based on the above embodiments, the step of obtaining and saving the call stack information of the client thread includes: Capture the stack trace information of the current thread; Filter stack trace information and remove framework method call records related to message tracing management; The filtered stack information is saved as a string.
[0027] Furthermore, the step of associating and storing the call stack information with the Message object includes: A weak reference mapping table is used to store the association between Message objects and client thread call stack information, where the Message object is used as the key and the corresponding call stack information string is used as the value.
[0028] Step 3: When the server thread retrieves and processes the Message object from the message queue, the application flow is triggered through the hooked dispatchMessage method, associating the current server thread with the Message object. Based on the above embodiments, the step of associating the current server thread with the Message object includes: The current server thread is associated with the Message object through a thread-local variable, wherein the thread-local variable stores a weak reference to the Message object being processed by the current thread.
[0029] Furthermore, when the loopOnce method, which is hooked, detects the end of a single message loop, it sets the weak reference of the Message object stored in the thread-local variable corresponding to the current thread to null.
[0030] Step 4: In response to the request to obtain stack information, determine whether the current thread is associated with a Message object that is being processed; if so, obtain the call stack information of the client thread associated with the Message object, and concatenate it with the stack information of the current server thread before outputting it; if not, directly output the stack information of the current thread.
[0031] Furthermore, the step of concatenating it with the stack information of the current server thread includes: Get the complete stack trace of the current server thread; Locate the call record of the message loop processing method in the stack trace information, and replace the part before the method call record with the call stack information of the client thread; The replaced client thread call stack information is concatenated with the remaining server thread call stack information in sequence to form a complete cross-thread call chain.
[0032] Based on the above embodiments, the method further includes an initialization step: Hook operations are performed by calling the initialization function of the Native layer during the Application initialization phase and when a new process is created in an Android application.
[0033] The Android cross-thread message tracing method provided in this embodiment achieves complete call chain tracing under the native Android cross-thread communication framework by hooking the underlying core message processing methods and associating them with the client and service thread stacks. By directly intercepting the critical communication path of the system's native layer, it avoids modifying the application source code and achieves a low-intrusion, low-performance-loss monitoring mechanism. Designed closely around the Android message loop mechanism, the solution can adapt to all cross-thread scenarios based on the Handler system, exhibiting high system universality. By using WeakHashMap and ThreadLocal to manage the lifecycle association between messages and stacks, it outputs clear and accurate fused stack information while ensuring memory safety. By providing an intuitive cross-thread call chain, it significantly improves the efficiency of multi-threaded debugging, exception location, and online problem diagnosis.
[0034] The method disclosed herein will be further described below with reference to a specific embodiment. The memory on the heap in the same process is shared, so Handler, Looper and Message can be directly obtained by other threads. Since some operations need to be performed in other threads, cross-thread communication is required.
[0035] The Handler holds a Looper, and the Looper holds a MessageQueue. The key to communication in the Java layer is the MessageQueue held by the Looper, i.e., the message queue. When using the Handler for communication, it assembles the Message and then notifies the Looper it holds. The Looper then uses the MessageQueue it holds to perform the actual cross-thread communication.
[0036] Android non-root Hook Java Method: Obtain the address of the Java method through C++, and replace the first N bytes of the address to achieve hooking.
[0037] This solution uses a Java Hook method to listen to the constructor of a Message and globally marks the Message so that the server thread can detect it when processing the Message. The specific solution is as follows: 0: Preliminary Preparations 001. Create a Java management class (MessageManager.Java) and declare static native methods that link to the C++ layer methods; init -> Calls the C++ method, hooking the C++ layer method, which is implemented in step 1; recordMessage\applyMessage\MessageOver -> is called by C++; getStack -> Used in Java, it calls a C++ method to get stack information in C++ and returns a list of strings containing stack information. 002. Declare a WeakHashMap with the key being Message and the value being String (stack information); 003. Declare and create a public ThreadLocal <WeakReference <message>> Store the message that each thread is currently processing; 004. The MessageManager.init method is called in the Application's onCreate method and when a new process is created.
[0038] 1: Implementation of the init method 101. During process initialization, use dlopen to dynamically link libart.so (the underlying implementations of Handler, Looper, and MessageQueue are all in this .so file). 102. Retrieve the enqueueMessage (Java's JNI method) symbol from the symbolic link table using dlsym; 103. Declare a C++ method for _enqueueMessage, with the same method signature as enqueueMessage, and create a global variable to record the address of the original enqueueMessage; 104. Implement _enqueueMessage, and use the passed parameters to call the MessageManager.recordMessage method; 105. Replace the address corresponding to the enqueueMessage symbol with the address of _enqueueMessage; 106. Repeat steps 102-105, changing the hook method from enqueueMessage to dispatchMessage and the method called to applyMessage; 106. Repeat steps 102-105, but change the hook method from enqueueMessage to loopOnce and the method called to MessageOver.
[0039] 2: C++ method call implementation 201. Implement the recordMessage method (a hook method of enqueueMessage); 202. recordMessage receives a Message object, uses the Thread.getStackTrace method to obtain the call stack, and retrieves the methods that are masked out by MessageManager; 203. Store the obtained stack trace using a WeakHashMap, with the Message object as the key and the stack trace information as the value; 204. Implement the applyMessage method (a hook method of dispatchMessage); 205. The `applyMessage` method receives a `Message` object, and the thread calling this method is already the target server thread; 206. Create a weak reference object for the Message and call ThreadLocal.set to set the Message that this thread is currently processing; 207. Implement the MessageOver method (a hook method of loopOnce); 208. The MessageOver method is still called in the server thread. It uses ThreadLocal.set to set the Message being processed by the current thread to null.
[0040] 3. getStack Implementation 301. Use ThreadLocal.get to check if the current thread is processing a Message; 302. If there is a Message being processed, obtain the call stack of the client thread through WeakHashMap; 303. Obtain the stack trace of the current thread using Thread.getStackTrace; 304. Retrieve Looper.loopOnce and replace its previous stack information with the call stack of the client thread; 305. If there is no message being processed, return the normal stack information directly; otherwise, return the concatenated stack information.
[0041] It should be understood that the various parts of this disclosure can be implemented in hardware, software, firmware, or a combination thereof.
[0042] The above description is merely a specific embodiment of this disclosure, but the scope of protection of this disclosure is not limited thereto. Any variations or substitutions that can be easily conceived by those skilled in the art within the scope of the technology disclosed in this disclosure should be included within the scope of protection of this disclosure. Therefore, the scope of protection of this disclosure should be determined by the scope of the claims.< / message>
Claims
1. A cross-thread message tracing method for Android, characterized in that, include: Step 1: During process initialization, intercept native methods related to message processing in the Android system through Hook operations; Step 2: When the client thread posts a Message object to the message queue, the recording process is triggered by the hooked enqueueMessage method to obtain and save the call stack information of the client thread, and store the call stack information with the Message object. Step 3: When the server thread retrieves and processes the Message object from the message queue, the application flow is triggered through the hooked dispatchMessage method, associating the current server thread with the Message object. Step 4: In response to the request to obtain stack information, determine whether the current thread is associated with a Message object that is being processed; if so, obtain the call stack information of the client thread associated with the Message object, and concatenate it with the stack information of the current server thread before outputting it. If not, output the current thread's stack information directly.
2. The method according to claim 1, characterized in that, Step 1 specifically includes: Step 1.1: Dynamically link the system library files to obtain the symbol address of the native method to be hooked; Step 1.2: Construct a replacement function with the same signature as the original method, and call the predefined Java layer callback interface in the replacement function; Step 1.3: Replace the execution address of the native method with the address of the replacement function to complete the Hook operation.
3. The method according to claim 2, characterized in that, The native methods to be hooked include the enqueueMessage method for adding messages to a queue, the dispatchMessage method for dispatching and processing messages, and the loopOnce method for marking the end of a single message loop.
4. The method according to claim 1, characterized in that, The step of obtaining and saving the call stack information of the client thread includes: Capture the stack trace information of the current thread; Filter stack trace information and remove framework method call records related to message tracing management; The filtered stack information is saved as a string.
5. The method according to claim 4, characterized in that, The step of associating and storing the call stack information with the Message object includes: A weak reference mapping table is used to store the association between Message objects and client thread call stack information, where the Message object is used as the key and the corresponding call stack information string is used as the value.
6. The method according to claim 1, characterized in that, The step of associating the current server thread with the Message object includes: The current server thread is associated with the Message object through a thread-local variable, wherein the thread-local variable stores a weak reference to the Message object being processed by the current thread.
7. The method according to claim 6, characterized in that, When the loopOnce method, which is hooked, detects that a single message loop has ended, it sets the weak reference of the Message object stored in the thread-local variable corresponding to the current thread to null.
8. The method according to claim 1, characterized in that, The step of concatenating it with the stack information of the current server thread includes: Get the complete stack trace of the current server thread; Locate the call record of the message loop processing method in the stack trace information, and replace the part before the method call record with the call stack information of the client thread; The replaced client thread call stack information is concatenated with the remaining server thread call stack information in sequence to form a complete cross-thread call chain.
9. The method according to claim 1, characterized in that, The method also includes an initialization step: Hook operations are performed by calling the initialization function of the Native layer during the Application initialization phase and when a new process is created in an Android application.