A low-performance-loss security point thread stack acquisition method and device and storage medium

By converting the Threads::print_on function in the OpenCV JDK source code into a global symbol and combining it with JVMTI to write dynamic libraries and proxy functions, the problem of thread stack acquisition in fullgc and high CPU states is solved, and thread stack acquisition with low performance loss is achieved.

CN116339866BActive Publication Date: 2025-10-10INTELLIGENT INTERNET (XIAMEN) HEALTH TECH CO LTD
View PDF 2 Cites 0 Cited by

Patent Information

Application Number
CN202310112365.2
Authority / Receiving Office
CN · China
Patent Type
Patents(China)
Current Assignee / Owner
Filing Date
2023-02-14
Publication Date
2025-10-10
Estimated Expiration
2043-02-14

AI Technical Summary

Technical Problem

The existing technology is difficult to effectively obtain the thread stack in fullgc and high CPU states, and has the problem of high performance consumption.

Method used

By converting the local symbol of the Threads::print_on function in the OpenCV JDK source code into a global symbol, and combining it with JVMTI to write a dynamic library and proxy function, we can obtain the thread stack through callback in the fullgc state, suspend the thread in the high CPU state and obtain the thread stack through the proxy function, thereby reducing performance loss.

Benefits of technology

Implemented low-performance-loss thread stack acquisition in fullgc and high CPU states, compatible with both states and reducing the impact on CPU performance.

✦ Generated by Eureka AI based on patent content.

Smart Images

  • Figure CN116339866B_ABST
    Figure CN116339866B_ABST
Patent Text Reader

Abstract

The application provides a low-performance-loss thread stack acquisition method and device and a storage medium, and the method comprises the following steps: converting a local symbol referenced by a Threads::print_on function in opencvjdk source code into a global symbol; judging whether the current system state is a fullgc state or a high CPU state; if the current system state is the fullgc state, calling Threads::print_on in callback to acquire a thread stack; if the current system state is the high CPU state, suspending all threads and acquiring the thread stack through a proxy function. In the application, the local symbol referenced by the Threads::print_on function in the opencvjdk source code is converted into the global symbol, and then the Threads::print_on function can be called externally, so that it can be used to acquire the thread stack; different thread stack acquisition methods are adopted according to different states, the performance of the CPU is not affected, and the thread stack acquisition under low performance loss is realized.
Need to check novelty before this filing date? Find Prior Art

Description

Technical Field

[0001] The present invention relates to the technical field of processor thread control, and in particular to a method, device and storage medium for obtaining a thread stack in a safe point with low performance loss. Background Art

[0002] Obtaining the thread stack can help you understand the current process running status (what each thread is doing, its running status, which thread number corresponds to the high CPU (high CPU means a thread that occupies too much CPU, such as more than 90%), which ones are stuck, etc.). Currently, there are several ways to obtain the Java thread stack:

[0003] (1)Official tool jstack: Generally, the thread stack can be obtained correctly.

[0004] (2) Async-profiler, a tool based on JVMTI and AsyncGetCallTrace: It is not restricted by safe points and is generally used for CPU sampling, which is different from thread stack acquisition.

[0005] (3) JVM variable HeapDumpBeforeFullGC: tells the virtual machine to dump the thread stack before fullgc.

[0006] Existing thread stack acquisition methods and their defects:

[0007] (1) jstack must enter a safe point to obtain all thread stacks, which cannot be obtained during fullgc.

[0008] (2) JVMTI does not need to enter a safe point when using AsyncGetCallTrace. However, if the thread has entered a safe point, it will fail to obtain the thread stack quickly. That is, it will not be able to obtain the details during fullgc. In other words, the failure of obtaining the thread stack during fullgc will not be changed.

[0009] (3) HeapDumpBeforeFullGC dumps the heap (including memory and thread stacks) before full GC. However, this method consumes a lot of performance and cannot be used in online systems.

[0010] (4) Under high CPU conditions, neither jstack nor AsyncGetCallTrace can take a higher priority to obtain the thread stack. Summary of the Invention

[0011] The present invention aims to solve one or more technical deficiencies in the above-mentioned prior art and proposes the following technical solutions.

[0012] A method for obtaining a thread stack in a safe point with low performance loss, the method comprising:

[0013] Converting the local symbol referenced by Threads::print_on function in opencvjdk source code into a global symbol in a conversion step;

[0014] Determining whether the current system state is a fullgc state or a high CPU state in a determination step;

[0015] If the current system state is a fullgc state, Threads::print_on is called in a callback to obtain the thread stack in an obtaining step; if the current system state is a high CPU state, all threads are suspended and a proxy function is used to obtain the thread stack.

[0016] Further, the operation of converting the local symbol into a global symbol is: using the python library lief to convert the local symbol into a global symbol, the local symbol including: gclog_or_tty, _ZN7Threads8print_onEP12outputStreambbb, _ZN9Arguments16_gc_log_filenameE, and _Z16ostream_init_logv.

[0017] Further, the operation of calling Threads::print_on in a callback to obtain the thread stack is: based on jvmti, a dynamic library is written, an event JVMTI_EVENT_GARBAGE_COLLECTION_START is registered, the event JVMTI_EVENT_GARBAGE_COLLECTION_START is activated when the current system state is a fullgc state, a callback function CallBack is activated through the activated event JVMTI_EVENT_GARBAGE_COLLECTION_START, Threads::print_on is called in the callback to print all thread stacks.

[0018] Further, if the current system state is a high CPU state, the operation of suspending all threads and obtaining the thread stack through a proxy function is: based on jvmti, a proxy function agent is written, a function inner_stack_tty is implemented in the agent to call the GetAllStackTraces function of jvmti to obtain all thread stacks, an external script is written and remotely injected into a target process when the high CPU state, the function inner_stack_tty in the agent is called in the target process to obtain all thread stacks, all threads are suspended, and Threads::print_on is called to print all thread stacks.

[0019] Further, the Threads::print_on prints the thread stack in the gclog_or_tty, and a user obtains the thread stack by parsing the gclog_or_tty.

[0020] The application further provides a low-performance-loss thread stack obtaining device at a safe point, which comprises:

[0021] A conversion unit is configured to convert a local symbol referenced by a Threads::print_on function in an opencvjdk source code into a global symbol.

[0022] A judgment unit is configured to judge whether a current system state is a fullgc state or a high CPU state.

[0023] An obtaining unit is configured to, if the current system state is the fullgc state, call the Threads::print_on to obtain the thread stack in a callback; and if the current system state is the high CPU state, suspend all threads and obtain the thread stack through a proxy function.

[0024] Further, the operation of converting the local symbol into the global symbol comprises: converting the local symbol into the global symbol by using a python library lief, and the local symbol comprises: gclog_or_tty, _ZN7Threads8print_onEP12outputStreambbb, _ZN9Arguments16_gc_log_filenameE, and _Z16ostream_init_logv.

[0025] Further, the operation of calling the Threads::print_on to obtain the thread stack in the callback comprises: writing a dynamic library based on jvmti, registering an event JVMTI_EVENT_GARBAGE_COLLECTION_START, activating the event JVMTI_EVENT_GARBAGE_COLLECTION_START when the current system state is the fullgc state, activating a callback function CallBack by using the activated event JVMTI_EVENT_GARBAGE_COLLECTION_START, and calling the Threads::print_on to print all thread stacks in the callback.

[0026] Furthermore, if the current system state is a high CPU state, all threads are suspended, and the operation of obtaining the thread stack through a proxy function is as follows: a proxy function agent is written based on jvmti, and a function inner_stack_tty is implemented in the agent to call the GetAllStackTraces function of jvmti to obtain all thread stacks. In the high CPU state, the written external script is remotely injected into a target process, and the function inner_stack_tty in the agent is called in the target process to obtain all threads and suspend all threads, and then Threads::print_on is called to print all thread stacks.

[0027] Furthermore, the Threads::print_on prints the thread stack in gclog_or_tty, and the user obtains the thread stack by parsing gclog_or_tty.

[0028] The present invention further provides a computer-readable storage medium, wherein the storage medium stores computer program code, and when the computer program code is executed by a computer, any one of the above methods is executed.

[0029] The technical effect of the present invention is: a method, device and storage medium for obtaining a thread stack in a safe point with low performance loss of the present invention, the method comprising: a conversion step S101, converting the local symbol referenced by the Threads::print_on function in the opencvjdk source code into a global symbol; a judgment step S102, judging whether the current system state is a fullgc state or a high CPU state; an acquisition step S103, if the current system state is a fullgc state, calling Threads::print_on in a callback to obtain the thread stack; if the current system state is a high CPU state, suspending all threads and obtaining the thread stack through a proxy function.In the present invention, the local symbol referenced by the Threads::print_on function in the opencvjdk source code is converted into a global symbol, and then the Threads::print_on function can be called externally, so that it can be used to obtain the thread stack, and then it is determined whether the current system state is fullgc state or high CPU state, and then different thread stack acquisition methods are adopted according to different states. If the current system state is fullgc state, Threads::print_on is called in the callback to obtain the thread stack; if the current system state is high CPU state, all threads are suspended and the thread stack is obtained through a proxy function, so that the method can obtain the thread stack in both fullgc state and high CPU state; in the present invention, in the fullgc state, a dynamic library is written based on jvmti, and the event JVMTI_EVENT_GARBAGE_COLLECTION_START is registered, and the event JVMTI_EVENT_GARBAGE_COLLEGE is activated when the current system state is fullgc state. CTION_START, activates the callback function CallBack through the activated event JVMTI_EVENT_GARBAGE_COLLECTION_START, and calls Threads::print_on in the callback to print all thread stacks. In the high CPU state, an agent function agent is written based on jvmti, and a function inner_stack_tty is implemented in the agent to call the GetAllStackTraces function of jvmti to obtain all thread stacks. In the high CPU state, the written external script is remotely injected into a target process, and the function inner_stack_tty in the agent is called in the target process to obtain all threads and suspend all threads, and then calls Threads::print_on to print all thread stacks. That is, the present invention specifically implements obtaining corresponding thread stacks by designing corresponding functions in two different states, so that the present invention can be compatible with two different states and basically has no effect on the performance of the CPU, that is, thread stack acquisition with low performance loss is achieved. BRIEF DESCRIPTION OF THE DRAWINGS

[0030] Other features, objects and advantages of the present application will become more apparent from the detailed description of non-limiting embodiments made with reference to the following drawings.

[0031] Figure 1 The present invention is a flowchart of a method for obtaining a thread stack in a safe point with low performance loss according to an embodiment of the present invention.

[0032] Figure 21 is a structural diagram of a thread stack acquisition device in a safe point with low performance loss according to an embodiment of the present invention. DETAILED DESCRIPTION

[0033] The present application will be further described in detail below with reference to the accompanying drawings and examples. It should be understood that the specific embodiments described herein are intended only to illustrate the relevant invention and are not intended to limit the invention. It should also be noted that, for ease of description, only portions relevant to the relevant invention are shown in the accompanying drawings.

[0034] It should be noted that, in the absence of conflict, the embodiments and features of the embodiments in this application can be combined with each other. The present application will be described in detail below with reference to the accompanying drawings and in combination with the embodiments.

[0035] Figure 1 A method for obtaining a thread stack in a safe point with low performance loss according to the present invention is shown, and the method includes:

[0036] Conversion step S101, converting the local symbols referenced by the Threads::print_on function in the opencvjdk source code into global symbols; in the present invention, through studying the fullgc process in the opencvjdk source code, it is found that the internal Threads::print_on function can be called in the fullgc process to print the thread stack. This function supports writing data to a specific file (such as gclog). Since Threads::print_on is an internal function and is not in the global area of ​​elf, it cannot be accessed externally under normal circumstances. Therefore, the present invention uses the Python library lief to convert several local symbols into global symbols for external calls, so that they can be used to obtain the thread stack. This is one of the important concepts of the present invention.

[0037] In step S102 , it is determined whether the current system state is a fullgc state or a high CPU state. The purpose of determining whether the current system state is a fullgc state or a high CPU state is to adopt different thread stack acquisition methods according to different system states to reduce power consumption.

[0038] Acquisition step S103: If the current system state is fullgc state, call Threads::print_on in the callback to obtain the thread stack; if the current system state is high CPU state, suspend all threads and obtain the thread stack through a proxy function.

[0039] In the present invention, the local symbol referenced by the Threads::print_on function in the opencvjdk source code is converted into a global symbol, and then the Threads::print_on function can be called externally, so that it can be used to obtain the thread stack, and then determine whether the current system state is fullgc state or high CPU state, and then adopt different thread stack acquisition methods according to different states. If the current system state is fullgc state, Threads::print_on is called in the callback to obtain the thread stack; if the current system state is high CPU state, all threads are suspended and the thread stack is obtained through a proxy function, so that the method can obtain the thread stack in both fullgc state and high CPU state, solves the defects in the background technology, and reduces power consumption, which is an important inventive concept of the present invention.

[0040] In a further embodiment, the operation of converting local symbols to global symbols is to use the Python library lief to convert the local symbols into global symbols. The local symbols include: gclog_or_tty, _ZN7Threads8print_onEP12outputStreambbb, _ZN9Arguments16_gc_log_filenameE, and _Z16ostream_init_logv. After these symbols are converted into global variables, Threads::print_on is called externally, and one or more of these symbols is used to record the thread stack.

[0041] In a further embodiment, if the current system state is fullgc state, the operation of calling Threads::print_on in the callback to obtain the thread stack is: writing a dynamic library based on jvmti, registering the event JVMTI_EVENT_GARBAGE_COLLECTION_START, activating the event JVMTI_EVENT_GARBAGE_COLLECTION_START when the current system state is fullgc state, activating the callback function CallBack through the activated event JVMTI_EVENT_GARBAGE_COLLECTION_START, and calling Threads::print_on in the callback to print all thread stacks.

[0042] In a further embodiment, if the current system state is a high CPU state, all threads are suspended, and the operation of obtaining the thread stack through a proxy function is as follows: a proxy function agent is written based on jvmti, and a function inner_stack_tty is implemented in the agent to call the GetAllStackTraces function of jvmti to obtain all thread stacks. In the high CPU state, the written external script is remotely injected into a target process, and the function inner_stack_tty in the agent is called in the target process to obtain all threads and suspend all threads, and then Threads::print_on is called to print all thread stacks.

[0043] In the present invention, in the fullgc state, a dynamic library is written based on jvmti, and the event JVMTI_EVENT_GARBAGE_COLLECTION_START is registered. When the current system state is fullgc state, the event JVMTI_EVENT_GARBAGE_COLLECTION_START is activated. The callback function CallBack is activated by the activated event JVMTI_EVENT_GARBAGE_COLLECTION_START, and Threads::print_on is called in the callback to print all thread stacks. In the high CPU state, an agent function agent is written based on jvmti, and a function in is implemented in the agent. ner_stack_tty is used to call the GetAllStackTraces function of jvmti to obtain all thread stacks. In the high CPU state, the written external script is remotely injected into a target process. In the target process, the function inner_stack_tty in the agent is called to obtain all threads and suspend all threads. Then, Threads::print_on is called to print all thread stacks. That is, the present invention specifically realizes obtaining corresponding thread stacks in two different states by designing corresponding functions, etc., so that the present invention can be compatible with two different states and basically has no effect on the performance of the CPU, that is, thread stack acquisition with low performance loss is realized, which is another important inventive concept of the present invention.

[0044] In a further embodiment, the Threads::print_on function prints the thread stack in gclog_or_tty, and the user can obtain the thread stack by parsing gclog_or_tty. The parsing method can read the content of gclog_or_tty and then display it to the user to help the user find the thread stack that caused the system failure.

[0045] Figure 2 The present invention shows a thread stack acquisition device in a safe point with low performance loss, which includes:

[0046] The conversion unit 201 converts the local symbols referenced by the Threads::print_on function in the opencvjdk source code into global symbols. In the present invention, through the study of the fullgc process in the opencvjdk source code, it is found that the internal Threads::print_on function can be called in the fullgc process to print the thread stack. The function supports writing data to a specific file (such as gclog). Since Threads::print_on is an internal function and is not in the global area of ​​elf, it cannot be accessed externally under normal circumstances. Therefore, the present invention uses the Python library lief to convert several local symbols into global symbols for external calls, so that they can be used to obtain the thread stack. This is one of the important concepts of the present invention.

[0047] The judging unit 202 judges whether the current system state is the fullgc state or the high CPU state. The purpose of judging whether the current system state is the fullgc state or the high CPU state is to adopt different thread stack acquisition methods according to different system states to reduce power consumption.

[0048] Acquisition unit 203, if the current system state is fullgc state, calls Threads::print_on in the callback to obtain the thread stack; if the current system state is high CPU state, suspends all threads and obtains the thread stack through a proxy function.

[0049] In the present invention, the local symbol referenced by the Threads::print_on function in the opencvjdk source code is converted into a global symbol, and then the Threads::print_on function can be called externally, so that it can be used to obtain the thread stack, and then determine whether the current system state is fullgc state or high CPU state, and then adopt different thread stack acquisition methods according to different states. If the current system state is fullgc state, Threads::print_on is called in the callback to obtain the thread stack; if the current system state is high CPU state, all threads are suspended and the thread stack is obtained through a proxy function, so that the method can obtain the thread stack in both fullgc state and high CPU state, solves the defects in the background technology, and reduces power consumption, which is an important inventive concept of the present invention.

[0050] In a further embodiment, the operation of converting local symbols to global symbols is to use the Python library lief to convert the local symbols into global symbols. The local symbols include: gclog_or_tty, _ZN7Threads8print_onEP12outputStreambbb, _ZN9Arguments16_gc_log_filenameE, and _Z16ostream_init_logv. After these symbols are converted into global variables, Threads::print_on is called externally, and one or more of these symbols is used to record the thread stack.

[0051] In a further embodiment, if the current system state is fullgc state, the operation of calling Threads::print_on in the callback to obtain the thread stack is: writing a dynamic library based on jvmti, registering the event JVMTI_EVENT_GARBAGE_COLLECTION_START, activating the event JVMTI_EVENT_GARBAGE_COLLECTION_START when the current system state is fullgc state, activating the callback function CallBack through the activated event JVMTI_EVENT_GARBAGE_COLLECTION_START, and calling Threads::print_on in the callback to print all thread stacks.

[0052] In a further embodiment, if the current system state is a high CPU state, all threads are suspended, and the operation of obtaining the thread stack through a proxy function is as follows: a proxy function agent is written based on jvmti, and a function inner_stack_tty is implemented in the agent to call the GetAllStackTraces function of jvmti to obtain all thread stacks. In the high CPU state, the written external script is remotely injected into a target process, and the function inner_stack_tty in the agent is called in the target process to obtain all threads and suspend all threads, and then Threads::print_on is called to print all thread stacks.

[0053] In the present invention, in the fullgc state, a dynamic library is written based on jvmti, and the event JVMTI_EVENT_GARBAGE_COLLECTION_START is registered. When the current system state is fullgc state, the event JVMTI_EVENT_GARBAGE_COLLECTION_START is activated. The callback function CallBack is activated by the activated event JVMTI_EVENT_GARBAGE_COLLECTION_START, and Threads::print_on is called in the callback to print all thread stacks. In the high CPU state, an agent function agent is written based on jvmti, and a function in is implemented in the agent. ner_stack_tty is used to call the GetAllStackTraces function of jvmti to obtain all thread stacks. In the high CPU state, the written external script is remotely injected into a target process. In the target process, the function inner_stack_tty in the agent is called to obtain all threads and suspend all threads. Then, Threads::print_on is called to print all thread stacks. That is, the present invention specifically realizes obtaining corresponding thread stacks in two different states by designing corresponding functions, etc., so that the present invention can be compatible with two different states and basically has no effect on the performance of the CPU, that is, thread stack acquisition with low performance loss is realized, which is another important inventive concept of the present invention.

[0054] In a further embodiment, the Threads::print_on function prints the thread stack in gclog_or_tty, and the user can obtain the thread stack by parsing gclog_or_tty. The parsing method can read the content of gclog_or_tty and then display it to the user to help the user find the thread stack that caused the system failure.

[0055] For the convenience of description, the above device is described as being divided into various units according to their functions. Of course, when implementing the present application, the functions of each unit can be implemented in the same or multiple software and / or hardware.

[0056] Through the description of the above embodiments, it can be seen that those skilled in the art can clearly understand that the present application can be implemented by means of software plus the necessary general hardware platform. Based on this understanding, the technical solution of the present application, or the part that contributes to the prior art, can be embodied in the form of a software product. The computer software product can be stored in a storage medium, such as ROM / RAM, a magnetic disk, an optical disk, etc., and includes a number of instructions for enabling a computer device (which can be a personal computer, a server, or a network device, etc.) to execute the devices described in various embodiments of the present application or certain parts of the embodiments.

[0057] Finally, it should be noted that the above embodiments are only intended to illustrate rather than limit the technical solutions of the present invention. Although the present invention has been described in detail with reference to the above embodiments, those skilled in the art should understand that the present invention can still be modified or replaced by equivalents. Any modification or partial replacement that does not depart from the spirit and scope of the present invention should be included in the scope of the claims of the present invention.

Claims

1. A method for obtaining thread stacks in a safe point with low performance loss, characterized in that: The method includes: The conversion step converts the local symbols referenced by the Threads::print_on function in the opencvjdk source code into global symbols. The operation of converting the local symbols into global symbols is as follows: using the Python library lief to convert the local symbols into global symbols. The local symbols include: gclog_or_tty, _ZN7Threads8print_onEP12outputStreambbb, _ZN9Arguments16_gc_log_filenameE, and _Z16ostream_init_logv; Determine whether the current system state is fullgc or the state of threads occupying more than 90% of the CPU; Acquisition steps: If the current system state is fullgc state, then write a dynamic library based on jvmti, register the event JVMTI_EVENT_GARBAGE_COLLECTION_START, activate the event JVMTI_EVENT_GARBAGE_COLLECTION_START when the current system state is fullgc state, activate the callback function CallBack through the activated event JVMTI_EVENT_GARBAGE_COLLECTION_START, call Threads::print_on in the callback to print all thread stacks; if the current system state is the state where more than 90% of the CPU threads are occupied, then write a based on jvmti An agent function is implemented in the agent, in which a function inner_stack_tty is implemented for calling the GetAllStackTraces function of the jvmti to obtain all thread stacks. When more than 90% of the CPU threads are occupied, an external script is remotely injected into a target process. In the target process, the function inner_stack_tty in the agent is called to obtain all threads and suspend all threads, and then Threads::print_on is called to print all thread stacks. Threads::print_on prints the thread stack in gclog_or_tty, and the user obtains the thread stack by parsing gclog_or_tty.

2. A thread stack acquisition device in a safe point with low performance loss, characterized in that: The device includes: A conversion unit converts the local symbols referenced by the Threads::print_on function in the opencvjdk source code into global symbols. The operation of converting the local symbols into global symbols is as follows: using the Python library lief to convert the local symbols into global symbols. The local symbols include: gclog_or_tty, _ZN7Threads8print_onEP12outputStreambbb, _ZN9Arguments16_gc_log_filenameE, and _Z16ostream_init_logv; A judgment unit determines whether the current system state is a fullgc state or a state where threads occupy more than 90% of the CPU; Get unit, if the current system state is fullgc state, then write a dynamic library based on jvmti, register the event JVMTI_EVENT_GARBAGE_COLLECTION_START, activate the event JVMTI_EVENT_GARBAGE_COLLECTION_START when the current system state is fullgc state, activate the callback function CallBack through the activated event JVMTI_EVENT_GARBAGE_COLLECTION_START, call Threads::print_on in the callback to print all thread stacks; if the current system state is the state of threads occupying more than 90% of the CPU, then write a based on jvmti An agent function is implemented in the agent, in which a function inner_stack_tty is implemented for calling the GetAllStackTraces function of the jvmti to obtain all thread stacks. When more than 90% of the CPU threads are occupied, an external script is remotely injected into a target process. In the target process, the function inner_stack_tty in the agent is called to obtain all threads and suspend all threads, and then Threads::print_on is called to print all thread stacks. Threads::print_on prints the thread stack in gclog_or_tty, and the user obtains the thread stack by parsing gclog_or_tty.

3. A computer-readable storage medium having computer program code stored thereon, wherein when the computer program code is executed by a computer, the method of claim 1 is executed.

Citation Information

Patent Citations

  • Refined process monitoring method and system based on watchdog in Linux system

    CN105677501A

  • Server-based microkernel operating system deployment method and operating system

    CN113127077A