Memóriaszivárgás Internet Explorer böngészőben
A memóriában „felejtett„ referencia nélküli objektumokat memóriahézagoknak (memory leak) nevezzük. A memóriaszivárgás programhiba, mert az objektumok által lefoglalt memóriaterület nincsen felszabadítva, miután már nincsen rájuk szükség.
Web oldalak esetében memóriaszivárgásról akkor beszélhetünk biztosan, ha a böngészőbe olvasott web lapot egymás után többször újratöltjük, miközben a böngésző memóriaigénye növekszik. Amikor egy másik web lapot olvas be a böngésző, vagy ugyanazt a web lapot újratöltjük, az előzőleg beolvasott web lap által elfoglalt memóriának fel kellene szabadulnia. Ha ez nem történik meg, memóriaszivárgásról beszélünk. Böngészőnk memóriaigénye megnő, és a teljesítménye is lecsökkenhet. Ilyenkor az egyetlen megoldás a böngészőt becsukni, majd újraindítani.
function CreateDivs(){
var oBigObject = new Array(1000).join(new Array(200).join("XXXXX"));
for(var i = 0; i < 50; i++){
var el = document.createElement('div');
el.id = 'myDiv'+ i;
el.className = 'box';
el.onclick = function(){
this.style.backgroundColor = 'red';
}
document.getElementsByTagName('body')[0].appendChild(el);
}
};
window.onload = function(){
CreateDivs();
}
A fenti kód memóriaszivárgást okoz Internet Explorer böngészőben. A fenti kódot tartalmazó web lapot Internet Explorer és Firefox böngészőkben próbáltam ki. A web lapot egymás után rövid időintervallumokban újratöltöttem, miközben monitoroztam a böngésző memóriafogyasztását. A memóriaszivárgás jól látható a memóriafoglalási grafikonon.
Az Internet Explorer memóriafogyasztása lépcsőzetesen nő, minden oldal frissítéssel. A lefoglalt memória akkor sem szabadult fel, miután egy teljesen üres web oldalat nyitottam meg a böngészőben.
A Firefox böngésző nem szivárogtatott memóriát, az allokált memóriát korrektül felszabadította.
Természetesen nemcsak Internet Explorernek vannak memóriaszivárgási gondjai. A leggyakrabban azonban mégis az Internet Explorer (főleg a 6-os és korábbi verziók) böngésző szokott memóriát szivárogtatni. Internet Explorer böngésző akkor szivárogtat memóriát, amikor körkörös hivatkozás jön létre egy JavaScript-objektum és egy befogadó környezet által nyújtott objektum (például DOM vagy ActiveX objektum) között. A továbbiakban a környezet által nyújtott objektumokat együttes néven csak COM-ként fogom említeni.
function leakMemory(){
var elDiv = document.getElementById('myDiv');
var jsObj = { 'div': elDiv };
elDiv.expandoProperty = jsObj;
}
A fenti kód körkörös hivatkozás memória szivárgást okoz. Az Internet Explorer nem képes felszabadítani ez elDiv és jsObj által allokált memóriát, csak a böngésző bezárásakor szabadul fel a memória.
Körkörös hivatkozás egy DOM elem és egy JavaScript-objektum között.
JavaScriptben DOM példányokat tetszőleges attribútumokkal bővíthetünk. Például:
var oEl = document.getElementById('myDiv');
Az így hozzáadott attribútumokat angolul expando property-nek nevezzük.
oEl.myprop = true;
Annak ellenére, hogy JavaScript GC-je képes feloldani a körkörös hivatkozásokat, ebben az esetben ez mégsem történik meg. Ennek az az oka, hogy a körkörös hivatkozás JavaScript és COM (DOM) objektum között jött létre, és a COM-nak más GC-je van. A COM komponensek a hivatkozások számlálásával oldják meg az általuk használt erőforrások felszabadítását (reference-counting garbage collection). Az új hivatkozások megnövelik, a megszűnő referenciák pedig csökkentik egy számláló értékét. Ha a számláló értéke nulla, a komponensre már nincs szükség, és felszabadítja a hozzá tartozó memóriaterületet. A módszer gyenge pontja az, hogy a körkörös hivatkozásokat nem képes felismerni.
Az elDiv hivatkozásszámlálójának értéke mindaddíg 1-es marad, amíg a jsObj JavaScript-objektum nincs felszabadítva, de jsObj-re elDiv hivatkozik. A két objektum által elfoglalt memória sosem lesz felszabadítva.
A böngészők memóriaszivárgása nem újkeletű probléma, csak sokáig nem tartották érdemlegesnek foglalkozni a problémával. A JavaScript megjelenése idején figyelmeztető üzenetek és popupok feldobálásán kívül másra nemigen volt használható. Az utóbbi időben azonban felvirágzásnak indult a JavaScript. A mai modern webalkalmazások felhasználói felülete hihetetlenül látványos és felhasználóbarát, majdnem asztali alkalmazásokra jellemző interakcióval. Ezeknek a megalkotásához elkerülhetetlenné vált különböző JavaScript osztálykönyvtárak fejlesztése, amik sokszor bizony elérik akár a száz kilobájtos fájlméretet is. Ilyen temérdek JavaScript kód futtatásakor már érdemes odafigyelni a memóriaszivárgás elkerülésére, hiszen a memóriaszivárgás jelentős mértékű lehet, ami néha akár a böngésző lefagyásához is vezethet.