In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-03-28 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Internet Technology >
Share
Shulou(Shulou.com)05/31 Report--
This article mainly introduces the relevant knowledge about the causes of memory leaks in JavaScript, the content is detailed and easy to understand, the operation is simple and fast, and it has a certain reference value. I believe you will gain something after reading this article on the causes of memory leaks in JavaScript. Let's take a look.
Leakage mode
In the following content, we will discuss the ways of memory leaks and give examples for each. One of the important examples is the Closure technology in JavaScript, and another example is the use of Closures in event execution. When you are familiar with this example, you will be able to identify and fix most of your existing memory leaks, but other Closure-related problems may be ignored.
Now let's take a look at these ways:
1. Circular reference (Circular References)-the object instance generated by the COM component of the IE browser and the object instance generated by the web script engine refer to each other, resulting in a memory leak. This is also the most common and major form of leakage we encounter on Web pages.
2. Internal function reference (Closures)-Closures can be regarded as a special form of circular applications that cause a lot of problems. Because of the dependence on specified keywords and syntax structures, Closures calls are easier for us to find.
3, page cross leak (Cross-Page Leaks)-page cross leak is actually a small leak, which is usually caused by internal object thinning during your browsing. We will discuss the insertion order of DOM below. In that example, you will find that with only a small amount of code changes, we can avoid the impact of object thinning on object construction.
4. Seemingly Pseudo-Leaks-this is not really a leak, but if you don't understand it, you may be extremely depressed when your available memory resources become less and less. To demonstrate this problem, we will cause a large amount of memory "leaks" by rewriting the contents of the Script element.
Circular reference
Circular references are basically the cause of all leaks. Typically, script engines handle circular references through the garbage collector (GC), but some unknown factors may prevent resources from being released from their environment. For IE, the state of some DOM object instances is not known to the script. Here are their basic principles:
Figure 1: basic circular reference model
The leakage problems caused in this model are based on the reference count of COM. The script engine object maintains references to the DOM object and waits for all references to be removed before cleaning up and releasing the DOM object pointer. In our example, we have two references on our script engine object: the script engine scope and the expando property of the DOM object.
The first reference is released when the script engine is terminated, and the DOM object reference is not released because it is waiting for the release of the script engine. You might think it would be easy to detect and fix hypothetical problems, but in fact such a basic example is just the tip of the iceberg. You may post loop references at the end of 30 object chains, which can be a nightmare to troubleshoot. If you still don't know how this leak works in HTML code, you can raise and expose it through a global script variable and a DOM object.
Var myGlobalObject; function SetupLeak () {/ / First set up the script scope to element reference myGlobalObject = document.getElementById ("LeakedDiv"); / / Next set up the element to script scope reference document.getElementById ("LeakedDiv"). ExpandoProperty = myGlobalObject;} function BreakLeak () {document.getElementById ("LeakedDiv"). ExpandoProperty = null;}
You can destroy the leak situation by directly making null worthwhile. Assigning a null value to the page document before unloading will let the script engine know that the reference chain between objects is gone. Now it will clean up the reference and release the DOM object normally. In this example, as a Web developer, you should know more about the relationships between objects.
As a basic case, circular references may have more complex representations. A common use for object-based JavaScript is to extend DOM objects by encapsulating JavaScript objects. During the build process, you often put a reference to the DOM object into the JavaScript object, as well as a reference to the newly created JavaScript object in the DOM object. Your application mode will make it very easy for two objects to access each other. This is a very straightforward circular reference problem, but you may not care because you use unused grammatical forms. To break this usage scenario may become more complex, of course, you can also use simple examples for clear discussion.
Function Encapsulator (element) {/ / Setup our element this.elementReference = element; / / Make our circular reference element.expandoProperty = this;} function SetupLeak () {/ / The leak happens all at once new Encapsulator (document.getElementById ("LeakedDiv"));} function BreakLeak () {document.getElementById ("LeakedDiv"). ExpandoProperty = null;}
A more complicated approach is to record all objects and properties that need to be dereferenced, and then clean them up when the Web document is unloaded, but most of the time you may cause additional leaks that don't solve your problem.
Closure function (Closures)
Because closure functions allow programmers to unwittingly create circular references, they often have unshirkable responsibility for resource leakage. Before the closure function itself is released, it is difficult to judge whether the parameters of the parent function and its local variables can be released. In fact, the use of closure functions is so common that there is nothing we can do when people encounter such problems frequently. After a detailed understanding of the problems behind closures and some special examples of closure leaks, we will combine the diagrams of loop references to find out where the closures are and where these unwelcome references come from.
Figure 2. Circular references caused by closure functions
Ordinary circular references are caused by two undetectable objects referencing each other, but closures are different. Instead of directly causing a reference, the closure function instead introduces information from its parent function scope. In general, the local variables and parameters of a function can only be used during the life cycle of the tuned function itself. When there is a closure function, the references of these variables and parameters will exist with the closure function, but because the closure function can exist beyond the life cycle of its parent function, the local variables and parameters in the parent function can still be accessed.
In the following example, parameter 1 will be released normally when the function call terminates. When we add a closure function, an additional reference is generated, and the reference is not released until the closure function is released. If you happen to put a closure function into an event, you have to manually remove it from that event. If you use the closure function as an expando attribute, you also need to clear it by setting null.
At the same time, the closure is created in each call, that is, when you call the function that contains the closure twice, you will get two separate closures, each with a reference to the parameter. Because of these obvious factors, closures are really very useful for causing leaks. The following example shows the main leakage factors for using closures:
Function AttachEvents (element) {/ / This structure causes element to ref ClickEventHandler element.attachEvent ("onclick", ClickEventHandler); function ClickEventHandler () {/ / This closure refs element}} function SetupLeak () {/ / The leak happens all at once AttachEvents (document.getElementById ("LeakedDiv"));} function BreakLeak () {}
If you are confused about how to avoid such leaks, I will tell you that dealing with it is not as simple as dealing with ordinary loop references. "closure" is regarded as a temporary object in the scope of the function. Once the function exits, you will lose the reference to the closure itself, so how do you call the detachEvent method to clear the reference? There is an interesting way to solve this problem on Scott Isaacs's MSN Spaces.
This method uses an additional reference (originally called second closure, but in this example there is only one closure) to assist the window object in executing the onUnload event. Because this additional reference and the reference of the closure exist in the same object domain, we can use it to release the event reference and complete the reference removal. For simplicity, we temporarily store a reference to the closure in an expando property, and the following example will show you how to release the event reference and clear the expando property.
Function AttachEvents (element) {/ / In order to remove this we need to put / / it somewhere. Creates another ref element.expandoClick = ClickEventHandler; / / This structure causes element to ref ClickEventHandler element.attachEvent ("onclick", element.expandoClick); function ClickEventHandler () {/ / This closure refs element}} function SetupLeak () {/ / The leak happens all at once AttachEvents (document.getElementById ("LeakedDiv"));} function BreakLeak () {document.getElementById ("LeakedDiv"). DetachEvent ("onclick", document.getElementById ("LeakedDiv") .uplodoClick); document.getElementById ("LeakedDiv"). ExpandoClick = null }
In this article, we are actually advised not to create and use closures unless we have to. The example in this article shows us the non-closure event reference method, that is, putting the closure function into the global scope of the page. When a closure function becomes an ordinary function, it no longer inherits the parameters and local variables of its parent function, so we don't have to worry about loop references based on closures. If we don't use closures when not necessary, we can try to avoid such problems in our code.
Finally, Eric Lippert of the script engine development group brings us a good article on the use of closures that is easy to understand. His final advice is to use closure functions only when it is really necessary. Although his article does not mention the real scenarios in which closures will be used, there are a large number of examples here that are very helpful to get started.
Page Cross leak (Cross-Page Leaks)
This kind of leakage problem, which is often caused by the insertion order, is mainly caused by the failure to clean and release temporary objects in the process of object creation. It typically occurs when a page element is dynamically created and added to the page DOM. One of the simplest example scenarios is that we dynamically create two objects and create a temporary Scope between the child element and the parent element.
Then, when you add a tree of these two parent-child structural elements to the page DOM tree, the two elements will inherit the hierarchical administrative domain object in the page DOM and leak the temporary domain object created before. The following illustration illustrates two ways to dynamically create and add elements to a page DOM. In the first method, we add each child element to its immediate parent element, and finally add the entire subtree created to the page DOM. When some relevant conditions are appropriate, this method will cause leakage due to temporary object problems. In the second approach, we create dynamic elements from top to bottom and add them to the page DOM structure as soon as they are created. Since each joined element inherits the domain object in the page DOM, we do not need to create any temporary time domain. This is a good way to avoid potential memory leaks.
Figure 3. DOM insertion sequence leakage model
Next, we will give an example of a leak that avoids most leak detection algorithms. Because we don't actually leak any visible elements, and because the leaked object is so small that you may not notice the problem at all. In order for our example to leak, we will have to inline a script function pointer in the dynamically created element structure. This will cause us to leak the internal temporary script object after we have set up the membership relationship between these elements. Because the leak is small, we have to execute the example thousands of times.
In fact, the leakage of an object has only a few bytes. After running the example and navigating the browser to a blank page, you will see the difference in memory usage between the two versions of the code. When we use the first method, adding child elements to their parent elements and then adding the resulting subtree to the page DOM, our memory usage increases slightly. This is a cross-navigation leak, and the leaked memory will only be freed when we restart the IE process. If you use the second method to add the parent element to the page DOM and then add the child element to its parent element, after running the same number of times, your memory usage will not rise again, and you will find that you have fixed the cross-navigation leak.
Function LeakMemory () {var hostElement = document.getElementById ("hostElement"); / / Do it a lot, look at Task Manager for memory response for (I = 0; I < 5000; iTunes +) {var parentDiv = document.createElement (""); var childDiv = document.createElement (""); / / This will leak a temporary object parentDiv.appendChild (childDiv); hostElement.appendChild (parentDiv); hostElement.removeChild (parentDiv); parentDiv.removeChild (childDiv); parentDiv = null; childDiv = null;} hostElement = null } function CleanMemory () {var hostElement = document.getElementById ("hostElement"); / / Do it a lot, look at Task Manager for memory response for (I = 0; I < 5000; iTunes +) {var parentDiv = document.createElement (""); var childDiv = document.createElement (""); / / Changing the order is important, this won't leak hostElement.appendChild (parentDiv); parentDiv.appendChild (childDiv); hostElement.removeChild (parentDiv); parentDiv.removeChild (childDiv); parentDiv = null ChildDiv = null;} hostElement = null;} Clean Insert
Such leaks should be clarified because this solution runs counter to some of our useful experiences in IE. Creating DOM elements with scripting objects and the interrelationships they have made are key points in understanding this leak. This is actually critical for leaks, because if we create DOM elements that don't contain any scripting objects and associate them in the same way, we won't have any leakage problems. The second technique given in the example may be more effective for a large subtree structure (since we have only two elements in that example, there is no efficiency problem in building a tree structure that is not related to the page DOM).
The second technique is that you don't associate any script objects at the beginning of creating elements, so you can safely create subtrees. After you associate your subtree to the page DOM, continue to process the script events you need. Keep in mind and follow the rules for the use of circular references and closure functions, and you won't encounter different leaks in your code when hooking up events.
I really want to point out this problem, because we can see that not all memory leaks are easy to detect. They may all be trivial problems, but it often takes thousands of times to execute a smaller leak scenario to make the problem manifest, just like the problem caused by the insertion order of DOM elements. If you think you can rest easy if you use the so-called "best" experience to program, but this example shows us that even the "best" experience seems to lead to leaks. Our solution here hopes to improve these existing good experiences, or introduce some new experiences so that we can avoid the possibility of leakage.
Seemingly leaked (Pseudo-Leaks)
Most of the time, the actual behavior of some APIs and their expected behavior may cause you to misjudge memory leaks. It seems that leaks occur most of the time in dynamic scripting operations on the same page, which is very rare when jumping from a page to a blank page. So how can you eliminate this problem like eliminating inter-page leaks, and whether the memory usage in the new task is what you expect? We will use a rewrite of the script text as an example of what appears to be a leak.
Like the DOM insertion order problem, this problem depends on the creation of temporary objects to generate "leaks." Rewrite the script text inside a script element object over and over again, and slowly you will begin to leak various script engine objects that have been associated with the overwritten content. In particular, objects related to script debugging are retained as full code objects.
Function LeakMemory () {/ / Do it a lot, look at Task Manager for memory response for (I = 0; I < 5000; iTunes +) {hostElement.text = "function foo () {}";}}
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.