天天看點

網站令浏覽器崩潰的原因

在網頁在裝載的過程中,常常由于種種原因使浏覽器的反映變的很慢,或造成浏覽器失去響應,甚至會導緻機器無法進行其他的操作。

  對于訪客,如果登入您網站,浏覽器就立刻崩潰,我想這對誰都是無法容忍的,對此總結了網站導緻浏覽器崩潰的原因:

1. 記憶體洩漏

  還是先談下記憶體洩漏,網站由于記憶體洩漏的而照成崩潰有兩種情況,伺服器的崩潰和浏覽器的崩潰。記憶體洩漏所造成的問題是顯而易見的,它使得已配置設定的記憶體的引用就會丢失,隻要系統還在運作中,則程序就會一直使用該記憶體。這樣的結果是,曾占用更多的記憶體的程式會降低系統性能,直到機器完全停止工作,才會完全清空記憶體。

  Apache的Web伺服器是用C/C++編寫的,C/C++的記憶體洩漏問題不必多說,系統中存在無法回收的記憶體,有時候會造成記憶體不足或系統崩潰。在Java中,記憶體洩漏就是存在一些被配置設定的可達而無用的對象,這些對象不會被GC所回收,然而它卻占用記憶體。

  而在用戶端,JavaScript所造成的記憶體洩漏,也将可能使得浏覽器崩潰。關于JavaScript的記憶體洩漏的文章,較權威的有《Memory leak patterns in JavaScript》和《Understanding and Solving Internet Explorer Leak Patterns》。

  JavaScript 是一種垃圾收集式(garbage collector,GC)語言,這就是說,記憶體是根據對象的建立配置設定給該對象的,并會在沒有對該對象的引用時由浏覽器收回。再根據《Fabulous Adventures In Coding》一文的說法:“JScript uses a nongenerational mark-and-sweep garbage collector.”,對” nongenerational mark-and-sweep”的可以這樣了解,浏覽器處理JavaScript并非采用純粹的垃圾收集,還使用引用計數來為Native對象(例如Dom、ActiveX Object)處理記憶體。

  在引用計數系統,每個所引用的對象都會保留一個計數,以獲悉有多少對象正在引用它。如果計數為零,該對象就會被銷毀,其占用的記憶體也會傳回給堆。 當對象互相引用時,就構成循環引用,浏覽器(IE6,Firefox2.0)對于純粹的JavaScript對象間的循環引用是可以正确處理的,但由于在引用計數系統,互相引用的對象都不能被銷毀,因為是引用計數永遠不能為零,是以浏覽器無法處理JavaScript與Native對象(例如Dom、ActiveX Object)之間循環引用。是以,當我們出現Native對象與JavaScript對象間的循環引用時,就會出現記憶體洩漏的問題。

  簡單來說就是,浏覽器使用引用計數來為Native對象處理記憶體,而引用計數的對象無法被銷毀,涉及Native對象的循環引用将會出現記憶體洩漏。配合下面的例子,了解這句話,基本上就可以了解JavaScript造成的記憶體洩漏了。

var obj;

window.onload = function (){

// JavaScript對象obj到DOM對象的引用,根據id獲得

obj = document.getElementById( " DivElement " );

  // DOM 對象則有到此 JavaScript 對象的引用,由expandoProperty實作

  document.getElementById( " DivElement " ).expandoProperty = obj;

};

  可見,JavaScript 對象和 DOM 對象間就産生了一個循環引用。由于 DOM 對象是通過引用計數管理的,是以兩個對象将都不能銷毀。

  另一種情況是閉包中,當碰到閉包,我們在Native對象上綁定事件響應代碼時,很容易制造出Closure Memory Leak。其關鍵原因和前者是一樣的,也是一個跨JavaScript對象和Native對象的循環引用。隻是代碼更為隐蔽。

window.onload = function AttachEvents(element){

  // element有個引用指向函數ClickEventHandler()

  element.attachEvent( " onclick " , ClickEventHandler);

function ClickEventHandler(){

// 該函數有個引用指向AttachEvents(element)調用Scope,    //也就是執行了參數element。

  }

}

  這裡簡單了解了JavaScript造成記憶體洩漏的原因,記憶體洩漏加大浏覽器的負擔,很有可能導緻浏覽器崩潰,我們要做的就是盡量去避免這種情況,做法可參考剛剛所說《Memory leak patterns in JavaScript》和《Understanding and Solving Internet Explorer Leak Patterns》兩篇文章加以了解。處理JavaScript記憶體洩漏最終目的還是要打破JavaScript對象和Native對象間的循環引用或者清零引用計數,釋放對象。

  一些記憶體洩漏如閉包記憶體洩漏,我們可能比較難以發現,記憶體洩漏的檢測我們可能參考《javascript 記憶體洩露工具使用》。

2. 網頁代碼複雜和浏覽器bug

  大量個人網站和低品質網站代碼的湧現造成對浏覽标準的普遍不支援,如果正好碰上浏覽器存在的一些bug,浏覽器渲染引擎在處理這些網頁代碼的時候會出錯,比如陷入死循環或直接崩潰等。

HTML代碼導緻網站崩潰

  這是HTML結構錯誤而導緻IE6的崩潰,在<col width="100"/>前或後添加任何字元均會導緻IE6 Crash。

<! DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd" >   < html > < head ></ head > < body >  < table >   < tr >   < td >   < table style ="width:100%;table-layout:fixed;" >   < colgroup >< col width ="100px" >< col ></ colgroup >   </ table >   </ td >   </ tr > < table > </ body > </ html >

  該代碼來個南韓的一個網站,無論是使用XHTML或者HTML的什麼版本,隻要帶了DOCTYPE聲明,IE6就會立即崩潰,當不帶DOCTYPE聲明的時候就沒有錯誤,原因可能跟文檔類型聲明有關。

令IE6崩潰的CSS代碼

  該代碼參考自網站Cats who Code。該Bug發現與2007年,據說是一名日本人發現的:

< style > * { position : relative } </ style > < table >< input ></ table >

  原因在于table中直接放置内容,在IE6會引起mshtml.dll子產品損壞而關閉浏覽器,非IE6則安全無恙。

  除此之外,存在于IE6的Bug還有下面這種情況,當僞類為 a:active 時同樣會遇到此問題:

< style type ="text/css" >   a { position : relative ; }   a:hover { float : left ; }   </ style > < a href ="" > 崩潰IE6 ,crash ie6 </ a >

  解決方案:為 <a> 添加 zoom:1; 令其觸發haslayout。

< style type ="text/css" >   a { position : relative ; zoom : 1 ; }   a:hover { float : left ; }   </ style >

令IE7崩潰的CSS代碼

  此Bug來自偷米飯,它隻存在IE7中據估計是處理省略字的時候導緻IE7崩潰。 

< style type ="text/css" >   div { float : left ; width : 175px ; }   ul { overflow : hidden ; white-space : nowrap ; text-overflow : ellipsis ; }   li { position : relative ; }   </ style > < div > < ul > < li > 崩潰崩潰崩潰崩潰崩潰crash ie7 </ li > < li > 崩潰崩潰崩潰崩潰崩潰crash ie7 </ li > </ ul > </ div >

  解決方案:為 <li> 添加 zoom:1; 令其觸發haslayout

令IE6崩潰的JavaScript代碼

  來自Internet Explorer Sucks,這個網站就是使用了一下代碼,當你使用IE6通路的時候,浏覽器将立刻崩潰。代碼如下:

< script > for (x in document.write) { document.write(x);} < / script>

  具體引起的原因暫時無法解析,但在相容性和執行效率來看一般不會采取這樣的寫法。

3. 網頁資料過多

  網頁含有大量需要處理的資料,造成系統繁忙,如多圖頁面,超長頁面等,或者網頁内嵌的各種控件會導緻浏覽器處理大量資料,造成系統繁忙。如Flash遊戲,ActiveX控件等。當浏覽器通路網站的時候,如果網站的資料量大,會使得浏覽器一般在處理過程中會占用很大的CPU使用率和記憶體、造成浏覽器失去響應,甚至會使電腦系統當機。在網站開發的時候,如果充分考慮Web性能,很大程度上能避免這個問題。

4. Ajax的Web服務漏洞

  Ajax的是基于XML的異步傳輸,文本格式的XML消息可能是二進制資料帶寬量的兩倍之多。傳輸XML消息所需的帶寬越多,系統或應用程式用來執行其他任務的可用資源就越少。例如執行複雜算法來擷取期望結果。

  過高的帶寬可能導緻由系統超載引起的性能減退。過高的帶寬将導緻Ajax應用程式輸出破損的資料,因為沒有足夠的資源生成幹淨的資料。這意味着Web服務門戶(Ajax應用程式屬于其中的一部分)将把破損資料暴露給門戶的其他部分,進而導緻畸形消息和過度解析。如果威脅者利用了這個漏洞,則會引起浏覽器崩潰。

  另外一方面,頻繁的、較小的 HTTP 請求會加重後端伺服器、負載均衡程式和防火牆的負擔,結果是造成過高的帶寬,最終導緻性能降低。如果用戶端長期停留在該頁面或沒有關閉浏覽器,會使得浏覽器的記憶體持續上漲,得不到釋放,導緻用戶端浏覽器崩潰。

  為此,在較多的時候Ajax的時候,我們要考慮通過專門的硬體加速器、優化軟體、消除代碼備援、XML加速功能和解決互操作性問題等方式加速Ajax應用程式。另外,積極地監視通信流可以持續地度量Ajax應用程式的網絡流量性能。通過将資料放入實時日志中,您可以檢視在哪些位置何時出現大量的包丢失和抖動事件,響應變慢的原因以及如何通過修改應用程式的優先級來改善通信流性能。

5. 其他原因

  除以上提到的原因之外,還有其他許多原因,雖然有些不會導緻浏覽器直接崩潰,但也會造成網站無法通路,如日志檔案導緻磁盤已滿、Web伺服器C指針錯誤、程序缺乏檔案描述符、線程死鎖、資料庫中的臨時表不夠用和伺服器超載等,可參考《導緻Web站點崩潰最常見的七大原因》。

總結

  對于訪客,如果登入您網站,浏覽器就立刻崩潰,我想這對誰都是無法容忍的,通過總結《網站令浏覽器崩潰的原因》,在我們從事網站開發維護的時候,我們應該盡量去避免記憶體洩漏、代碼錯誤和備援及資料量過大等問題,建構更佳性能的站點。

PS:本文由維奇總結,如有轉載請注明出處,錯漏之處歡迎大家留言指出,謝謝!

本文位址:http://www.cnblogs.com/wiky/archive/2010/01/16/website-makes-browser-crash-reasons.html 

參考資料

  Memory leak patterns in JavaScript

  Understanding and Solving Internet Explorer Leak Patterns

  IE's memory-leak fix greatly exaggerated

  Fabulous Adventures In Coding

  JavaScript記憶體洩漏

  6 html and javascript codes to crash

  IE6導緻Web站點崩潰的原因分析

  提高Ajax應用程式性能,避開Web服務漏洞

分類:  (X)HTML/CSS, JavaScript, Tips, 使用者體驗 标簽:  浏覽器,  tips,  總結

繼續閱讀