Javascript memory leak on the collation of draft issues

sponsored links
Wrote a long time a small javascript function modules, has never been concerned about the issue of memory leaks. Remember to write C + + procedures, memory leak is a serious issue, I think it is time for a look. Find the articles online, Mark look. Original Address: http://www.blogjava.net/tim-wu/archive/2006/05/29/48729.html

Conventional circular reference memory leak and memory leak Closure

To learn more about javascript memory leak problem, first of all have to understand is that the GC principles of javascript.

I remember the original books in the rhino "JavaScript: The Definitive Guide" in the seen, IE is the use of the GC algorithm counters, therefore, only when it will cause a circular reference memory leakage. And subsequently has been observed that the phenomenon is very different articles until you see Eric, they would understand the rhinoceros did not say the book is very clear, it is estimated that the book have been written after the IE upgrade your algorithm. In IE 6, the javascript object for internal, jscript using mark-and-sweep algorithm, and the javascript object and external object (including the native object and vbscript object, etc.) applied, IE 6 is the counter used algorithm.

Eric Lippert in a http://blogs.msdn.com/ericlippert/archive/2003/09/17/53038.aspx mentioned JScript in IE 6 using the GC algorithm is nongeneration mark-and-sweep. Javascript on the algorithm for the realization of shortcomings, the article says:
"The benefits of this approach are numerous, but the principle benefit is that circular references are not leaked unless the circular reference involves an object not owned by JScript."
In other words, IE 6 for Script Objects purely between the Circular References can be handled correctly, but it can not be dealt with JScript and Native Object (such as the Dom, ActiveX Object) between Circular References.
Therefore, when we emerged Native objects (such as the Dom, ActiveX Object) and Javascript circular reference between the object, the memory leak problems have emerged. Of course, the bug in IE 7 has been fixed in [http://www.quirksmode.org/blog/archives/2006/04/ie_7_and_javasc.html].

There is a diagram http://msdn.microsoft.com/library/default.asp?url=/library/en-us/IETechCol/dnwebgen/ie_leak_patterns.asp simple example and exemplifies this problem:
< html > 
     < head > 
         < script language = " JScript " > 

         var  myGlobalObject;

         function  SetupLeak()  //  Produce a circular reference, so will cause a memory leak  
        {
             //  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()  //  Unpack the circular reference problem, resolve the memory leak  
        {
            document.getElementById( " LeakedDiv " ).expandoProperty  = 
                 null ;
        }
         </ script > 
     </ head > 

     < body onload = " SetupLeak() "  onunload = " BreakLeak() " > 
         < div id = " LeakedDiv " ></ div > 
     </ body > 
</ html >

The above examples may seem very simple to solve the memory leak problem. Unfortunately, when our code after the structure of the complex, resulting in circular reference has become a variety of reasons, we can not so easily observed, this time, we must be careful code inspection.
Especially when it comes to Closure, when we go to the Native objects (such as the Dom object, ActiveX Object) on the binding events in response to the code, a careless, we will create Closure Memory Leak. The key reason, in fact, and the former is the same, but also a cross-javascript object and the native object circular reference. Just more hidden code, the hidden nature is the result of javascript caused by the language features. However, embedded in the use of a similar function, the built-in function has to have a reference point to the external function of scope, including the external function parameters, so it is likely to result in a very subtle circular references, for example:
DOM_Node.onevent -> function_object. [[Scope]] -> scope_chain -> Activation_object.nodeRef -> DOM_Node.

[Http://msdn.microsoft.com/library/default.asp?url=/library/en-us/IETechCol/dnwebgen/ie_leak_patterns.asp] have a very profound examples show the hidden nature:
< html > 
     < head > 
         < script language = " JScript " > 

         function  AttachEvents(element)
        {
             //  This structure causes element to ref ClickEventHandler  //element There is a reference point to functions ClickEventHandler  () 
            element.attachEvent( " onclick " , ClickEventHandler);

             function  ClickEventHandler()
            {
                 //  This closure refs element  // The function has a reference point to AttachEvents  (element) Calling Scope, that is, perform an argument element.  
                
            }
        }

         function  SetupLeak()
        {
             //  The leak happens all at once 
            AttachEvents(document.getElementById( " LeakedDiv " ));
        }

         </ script > 
     </ head > 

     < body onload = " SetupLeak() "  onunload = " BreakLeak() " > 
         < div id = " LeakedDiv " ></ div > 
     </ body > 
</ html >

This example also in the same reason in IE 6 will cause leakage

function  leakmaybe() {
var  elm  =  document.createElement( " DIV " );
  elm.onclick  =   function () {
return   2   +   2 ;
  }
}

for  ( var  i  =   0 ; i   10000 ; i ++ ) {
  leakmaybe();
}


btw:
Closure of knowledge on, we will look at this article http://jibbering.com/faq/faq_notes/closures.html, habits can also take a look at the Chinese zkjbeyond the blog, he Closure This article provides a brief translation: http://www.blogjava.net/zkjbeyond/archive/2006/05/19/47025.html. The reason why there will be a series of problems, the key is that javascript is a script function to resolve language in javascript "function is to define the scope of variable scope, rather than dynamic scope", this book in the rhino "JavaScript: The Definitive Guide" in "Funtion" as discussed in the chapter.
http://support.microsoft.com/default.aspx?scid=KB; EN-US; 830555 on this issue also give a very detailed example.

Some simple solutions

Ajax front-end most of the javascript framework used in the management of the incident to address the problem.

If you need to solve this problem, you can refer to the following methods:

http://outofhanwell.com/ieleak/index.php?title=Main_Page: there is a good tool for the detection
http://youngpup.net/2005/0221010713 mentioned: Dom can make use of recursive trees, the lifting of the binding event, thereby lifting the circular reference:

														
      if (window.attachEvent) {
          var clearElementProps = [
              'data',
              'onmouseover',
              'onmouseout',
              'onmousedown',
              'onmouseup',
              'ondblclick',
              'onclick',
              'onselectstart',
              'oncontextmenu'
          ];

          window.attachEvent("onunload", function() {
              var el;
              for(var d = document.all.length;d--;){
                  el = document.all[d];
                  for(var c = clearElementProps.length;c--;){
                      el[clearElementProps[c]] = null;
                  }
              }
          });
      }												


The article http://novemberborn.net/javascript/event-cache through increased EventCache, which gives a relatively structured solutions
/*     EventCache Version 1.0
    Copyright 2005 Mark Wubben

    Provides a way for automagically removing events from nodes and thus preventing memory leakage.
    See <http://novemberborn.net/javascript/event-cache> for more information.
    
    This software is licensed under the CC-GNU LGPL <http://creativecommons.org/licenses/LGPL/2.1/>
*/ 

/*     Implement array.push for browsers which don't support it natively.
    Please remove this if it's already in other code  */ 
if (Array.prototype.push  ==   null ){
    Array.prototype.push  =   function (){
         for ( var  i  =   0 ; i  <  arguments.length; i ++ ){
             this [ this .length]  =  arguments[i];
        };
         return   this .length;
    };
};

/*     Event Cache uses an anonymous function to create a hidden scope chain.
    This is to prevent scoping issues.  */ 
var  EventCache  =   function (){
     var  listEvents  =  [];
    
     return  {
        listEvents : listEvents,
    
        add :  function (node, sEventName, fHandler, bCapture){
            listEvents.push(arguments);
        },
    
        flush :  function (){
             var  i, item;
             for (i  =  listEvents.length  -   1 ; i  >=   0 ; i  =  i  -   1 ){
                item  =  listEvents[i];
                
                 if (item[ 0 ].removeEventListener){
                    item[ 0 ].removeEventListener(item[ 1 ], item[ 2 ], item[ 3 ]);
                };
                
                 /*  From this point on we need the event names to be prefixed with 'on"  */ 
                 if (item[ 1 ].substring( 0 ,  2 )  !=   " on " ){
                    item[ 1 ]  =   " on "   +  item[ 1 ];
                };
                
                 if (item[ 0 ].detachEvent){
                    item[ 0 ].detachEvent(item[ 1 ], item[ 2 ]);
                };
                
                item[ 0 ][item[ 1 ]]  =   null ;
            };
        }
    };
}();

Is also very simple to use:

												
<script type="text/javascript">
function addEvent(oEventTarget, sEventType, fDest){
        if(oEventTarget.attachEvent){
		oEventTarget.attachEvent("on" + sEventType, fDest);
	} elseif(oEventTarget.addEventListener){
		oEventTarget.addEventListener(sEventType, fDest, true); 
	} elseif(typeof oEventTarget[sEventType] == "function"){
                var fOld = oEventTarget[sEventType];
		oEventTarget[sEventType] = function(e){ fOld(e); fDest(e); };
	} else {
		oEventTarget[sEventType] = fDest;
	};

	/* Implementing EventCache for all event systems */
	EventCache.add(oEventTarget, sEventType, fDest, true);
};


function createLeak(){
         var body = document.body;

	function someHandler(){
               return body;
	};

	addEvent(body, "click", someHandler);
};

window.onload = function(){
       var i = 500;
       while(i > 0){
		createLeak();
		i = i - 1;
	}
};

window.onunload = EventCache.flush;
</script>													


http://talideon.com/weblog/2005/03/js-memory-leaks.cfm way a text like this:
/* 
 * EventManager.js
 * by Keith Gaughan
 *
 * This allows event handlers to be registered unobtrusively, and cleans
 * them up on unload to prevent memory leaks.
 *
 * Copyright (c) Keith Gaughan, 2005.
 *
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Common Public License v1.0
 * (CPL) which accompanies this distribution, and is available at
 * http://www.opensource.org/licenses/cpl.php
 *
 * This software is covered by a modified version of the Common Public License
 * (CPL), where Keith Gaughan is the Agreement Steward, and the licensing
 * agreement is covered by the laws of the Republic of Ireland.
  */ 

//  For implementations that don't include the push() methods for arrays. 
if  ( ! Array.prototype.push) {
    Array.prototype.push  =   function (elem) {
         this [ this .length]  =  elem;
    }
}

var  EventManager  =  {
    _registry:  null ,

    Initialise:  function () {
         if  ( this ._registry  ==   null ) {
             this ._registry  =  [];

             //  Register the cleanup handler on page unload. 
            EventManager.Add(window,  " unload " ,  this .CleanUp);
        }
    },

     /* *
     * Registers an event and handler with the manager.
     *
     * @param  obj         Object handler will be attached to.
     * @param  type        Name of event handler responds to.
     * @param  fn          Handler function.
     * @param  useCapture  Use event capture. False by default.
     *                     If you don't understand this, ignore it.
     *
     * @return True if handler registered, else false.
      */ 
    Add:  function (obj, type, fn, useCapture) {
         this .Initialise();

         //  If a string was passed in, it's an id. 
         if  ( typeof  obj  ==   " string " ) {
            obj  =  document.getElementById(obj);
        }
         if  (obj  ==   null   ||  fn  ==   null ) {
             return   false ;
        }

         //  Mozilla/W3C listeners? 
         if  (obj.addEventListener) {
            obj.addEventListener(type, fn, useCapture);
             this ._registry.push({obj: obj, type: type, fn: fn, useCapture: useCapture});
             return   true ;
        }

         //  IE-style listeners? 
         if  (obj.attachEvent  &&  obj.attachEvent( " on "   +  type, fn)) {
             this ._registry.push({obj: obj, type: type, fn: fn, useCapture:  false });
             return   true ;
        }

         return   false ;
    },

     /* *
     * Cleans up all the registered event handlers.
      */ 
    CleanUp:  function () {
         for  ( var  i  =   0 ; i  <  EventManager._registry.length; i ++ ) {
             with  (EventManager._registry[i]) {
                 //  Mozilla/W3C listeners? 
                 if  (obj.removeEventListener) {
                    obj.removeEventListener(type, fn, useCapture);
                }
                 //  IE-style listeners? 
                 else   if  (obj.detachEvent) {
                    obj.detachEvent( " on "   +  type, fn);
                }
            }
        }

         //  Kill off the registry itself to get rid of the last remaining 
         //  references. 
        EventManager._registry  =   null ;
    }
};

Is also very simple to use

<html>
<head>
<script type=text/javascript src=EventManager.js></script>
<script type=text/javascript>
    function onLoad() {

    EventManager.Add(document.getElementById(testCase),click,hit );
returntrue;
    }

    function hit(evt) {
        alert(click);
    }
</script>
</head>

<body onload='javascript: onLoad();'>

<div'width:100%; height: 100%; background-color: yellow;'>
  <h1>Click me!</h1>
</div>

</body>
</html>


google map api to provide the same function of a similar use of the page unload event to address the Closure of the memory leak problem caused.
Of course, if you are too troublesome, you can for each and the native object on the Arab-Israeli vascript object to prepare a destoryMemory function, used to manually call in order to manually lift the Dom object binding events.

There is also a people should not be OO, abandoned Dom characteristics, using innerHTML instead of appendChild, to avoid circular reference. Detailed discussion see http://birdshome.cnblogs.com/archive/2005/02/16/104967.html paste.

Cross-Page Leaks

Cross-Page Leaks and referred to the next section Pseudo-Leaks in my view, is that IE's bug, though MS does not recognize Die face piray :)

We can look at this example code:
< html > 
     < head > 
         < script language = " JScript " > 

         function  LeakMemory()  //  This function will throw a Cross  -Page Leaks 
        {
             var  hostElement  =  document.getElementById( " hostElement " );

             //  Do it a lot, look at Task Manager for memory response 

             for (i  =   0 ; i  <   5000 ; i ++ )
            {
                 var  parentDiv  = 
                    document.createElement( " <div> " );
                 var  childDiv  = 
                    document.createElement( " <div> " );

                 //  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()  //  This function does not throw a Cross  -Page Leaks 
        {
             var  hostElement  =  document.getElementById( " hostElement " );

             //  Do it a lot, look at Task Manager for memory response 

             for (i  =   0 ; i  <   5000 ; i ++ )
            {
                 var  parentDiv  =   document.createElement( " <div> " );
                 var  childDiv  =   document.createElement( " <div> " );

                 //  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 ;
        }
         </ script > 
     </ head > 

     < body > 
         < button onclick = " LeakMemory() " > Memory Leaking Insert </ button > 
         < button onclick = " CleanMemory() " > Clean Insert </ button > 
         < div id = " hostElement " ></ div > 
     </ body > 
</ html >

LeakMemory and function of these two CleanMemory The only difference is that their sequential code from code point of view, the logic of the two codes are not wrong.

However, it will cause leaks LeakMemory. The reason is that LeakMemory () will be established and parentDiv link between childDiv, this time, in order to be able to learn childDiv information parentDiv, IE, therefore need to create a temporary object scope. ParentDiv then set up the link and hostElement object, parentDiv and childDiv page document Direct access to the scope. Unfortunately, IE will not release just the scope of that object temporary memory space, until we Jump the page, this space can be released. And CleanMemory function, he first hostElement networking parentDiv and then again childDiv and networking parentDiv, this process does not require a separate establishment of a temporary scope, as long as the direct use of the scope page document can be, so it will not cause a memory leak

Detailed reasons, we will look at this article http://msdn.microsoft.com/library/default.asp?url=/library/en-us/IETechCol/dnwebgen/ie_leak_patterns.asp.

btw:
IE 6 in the garbage collection algorithm, that is, directly from the "in scope" to mark the beginning of the object removed:
Every variable which is "in scope" is called a "scavenger". A scavenger may refer to a number, an object, a string, whatever. We maintain a list of scavengers - variables are moved on to the scav list when they come into scope and off the scav list when they go out of scope.

Pseudo-Leaks

This is called "leakage Soo funny " It's appropriate ah:)
Take a look at this example:
< html > 
     < head > 
         < script language = " JScript " > 

         function  LeakMemory()
        {
             //  Do it a lot, look at Task Manager for memory response 

             for (i  =   0 ; i  <   5000 ; i ++ )
            {
                hostElement.text  =   " function foo() { } " ; //See memory will increase  
            }
        }
         </ script > 
     </ head > 

     < body > 
         < button onclick = " LeakMemory() " > Memory Leaking Insert </ button > 
         < script id = " hostElement " > function  foo() { } </ script > 
     </ body > 
</ html >

MS is so interpreted, it is not memory leak. If you create a lot of lack of access to the object can not be released, it is the memory leak. Here, you will create a number of elements, Internet Explorer need to preserve them to show the correct page. Internet Explorer does not know that you will not control you just created to run the script all of these objects. Disappear when the page (when you finished, leave the browser) will release memory. It will not leak. When the destruction of the page, it will interrupt the circular reference.

Oh ~ ~ ~

Detailed reasons, we will look at this article http://msdn.microsoft.com/library/default.asp?url=/library/en-us/IETechCol/dnwebgen/ie_leak_patterns.asp.

The attention of a number of other minor points

Variables must be defined var, otherwise, by the implicit variable declarations are global variables, not local variables;
Global variables to remember to buy when no null;
The attention of the proper use of delete, delete some useless function attributes;
The attention of the proper use of try ... cache, to ensure that the place to be null and void invoke the correct implementation of the code;
out of the window open even close, and it is still the window object, we must remember to delete reference;
the frame and iframe and similar window.

Reference

http://jibbering.com/faq/faq_notes/closures.html
http://javascript.weblogsinc.com/2005/03/07/javascript-memory-leaks/
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/IETechCol/dnwebgen/ie_leak_patterns.asp
http://72.14.203.104/search?q=cache:V9Bt4_HBzQ8J:jgwebber.blogspot.com/2005/01/dhtml-leaks-like-sieve.html + DHTML + Leaks + Like + a + Sieve + & hl = zh - CN & ct = clnk & cd = 9 (this is DHTML Leaks Like a Sieve) a text in google's cache, the original has a crawl)
http://spaces.msn.com/siteexperts/Blog/cns!1pNcL8JwTfkkjv4gg6LkVCpw!338.entry
http://support.microsoft.com/default.aspx?scid=KB; EN-US; 830555
http://www.ajaxtopics.com/leakpatterns.html
http://blogs.msdn.com/ericlippert/archive/2003/09/17/53028.aspx
http://www.quirksmode.org/blog/archives/2005/02/javascript_memo.html
http://youngpup.net/2005/0221010713
http://blogs.msdn.com/ericlippert/archive/2003/09/17/53038.aspx =
http://support.microsoft.com/kb/266071/EN-US ==> IE 5.0 to version 5.5 some of the GC bug
http://www.quirksmode.org/blog/archives/2006/04/ie_7_and_javasc.html ==> ie 7 Improvement
http://erik.eae.net/archives/2006/04/26/23.23.02/ ==> ie 7 Improvement
http://www.feedbackarchive.com/spamvampire/today.html ==> Try this script for memory leaks - it leaked 50 megabytes in 15 minutes with firefox on linux:
http://birdshome.cnblogs.com/archive/2005/02/15/104599.html
http://www.quirksmode.org/dom/innerhtml.html
http://www.crockford.com/javascript/memory/leak.html
"JavaScript: The Definitive Guide" 4th Edition
http://outofhanwell.com/ieleak/index.php?title=Main_Page
  • del.icio.us
  • StumbleUpon
  • Digg
  • TwitThis
  • Mixx
  • Technorati
  • Facebook
  • NewsVine
  • Reddit
  • Google
  • LinkedIn
  • YahooMyWeb

Related Posts of Javascript memory leak on the collation of draft issues

  • JavaScript Advanced Training - Custom Object

    First, an overview of In the Java language, we can define your own categories, and in accordance with these classes to create objects to use in Javascript, we can also define your own categories, such as the definition of User category, Hashtable cat ...

  • Understanding of JavaScript closures

    Understanding of JavaScript closures To become advanced JavaScript programmers, it is necessary to understand the closure. In this paper, ECMA 262 specification explain the closure of the internal working mechanism for JavaScript programmers understanding

  • javascript object-oriented technology foundation (1)

    Read a lot of javascript introduction of object-oriented technology article, I am very dizzy. Why? Not because of poorly written, but because too esoteric. javascript objects not explain how matter, went one up on the subject, class / inheritance / p ...

  • Practical small JavaScript function (1)

    1. To confirm the deletion 2. Factorials 3. Object-oriented - inheritance (with prototype) 4.js object-oriented - many states See the same name download

  • Rails to monitor the process of memory leaks skills

    Rails applications easier to encounter two types of performance problems: Rails implementation of a class are very slow, CPU consumption too high; The other is the process of memory leaks Rails. To resolve these two types of questions are necessary before

  • and analysis of the use of DWR

    1. Download dwr.jar, to add it to WEB-INF/lib directory 2. Modify web.xml file, add the mapping DWRServlet <servlet> <servlet-name> dwr-invoker </ servlet-name> <servlet-class> org.directwebremoting.servlet.DwrServlet </ se ...

  • Javascript in the browser environment (vi) incident

    Matter Examples of a lot of events. Such as user input, the click of a button and so on. Can put a javascript function assigned to an event (this can be called the event listener or event handler), when the incident happened, and will perform this functio

  • ruby MBARI large patches Performance Evaluation Report

    Before JavaEye news ruby memory leak culprit - the specter of a detailed analysis of the current pointer Ruby official version (MRI version) causes memory leaks. Brent Roman today issued a Super patch , Which contains 6 patch file to resolve the Ruby ...

  • js events dynamically add and write-off

    IE's JScript existence of memory leak bug must we all know or have heard of. This is because of IE's memory recovery manager of a design error. When we create a prepared script when a cross-reference, for example, the following code: window.o ...

blog comments powered by Disqus
Recent
Recent Entries
Tag Cloud
Random Entries