2009-05-14 10 views
279

JavaScriptのガベージコレクションとは何ですか?より良いコードを書くために、ウェブプログラマーがJavaScriptガベージコレクションについて理解するために重要なことは何ですか?JavaScriptガベージコレクションとは何ですか?

+3

も参照してください。http://stackoverflow.com/questions/774357/garbage-collection –

+1

また、[JavaScriptのガベージコレクションの仕組みは?](http://stackoverflow.com/q/4324133/1048572) – Bergi

答えて

185

エリックリペットは(さらにVBScriptのとの比較)しばらく前にこのテーマについてdetailed blog postを書きました。より正確に言えば、彼は約JScriptと書いています。これはマイクロソフト独自のECMAScriptの実装ですが、JavaScriptによく似ています。私は、Internet ExplorerのJavaScriptエンジンで大部分の動作が同じになると想定できると思います。もちろん、実装はブラウザによって異なりますが、いくつかの共通原則を使用して他のブラウザに適用できると思われます。そのページから引用

JScriptでは、nongenerational マークアンドスイープガベージコレクタを使用しています。また、このような 作品: 「スコープ内」であるすべての変数は、「スカベンジャー」と呼ばれている

  • 。スカベンジャー は数字、オブジェクト、 文字列を参照することがあります。スカベンジャーのリスト を保持します。 がスコープリストに移動すると、 がスコープに、 がスコープ外になるときにスカブリストから変数が移動します。

  • いつもゴミは コレクタが実行されます。まず、すべてのオブジェクト、変数、 文字列などに「 」というマークを付けます。すべてのメモリはGCによって と追跡されます。 (JScriptでは、内部VARIANT データ構造を使用し、そこ は 構造内の余分な未使用ビットがたくさんあるので、我々はそれら のいずれかを設定します。)

  • 第二に、それは スカベンジャーと上のマークをクリアスカベンジャー参照の推移的閉鎖 。したがって、 スカベンジャーオブジェクトが 非スカベンジャーオブジェクトを参照している場合、非スカベンジャーの ビットをクリアし、それが参照するものすべてを にクリアします。 ( 投稿と異なる意味で という語で「クロージャ」という言葉を使用しています。)

  • この時点ではまだマークされたすべての メモリは任意のスコープ内の変数から任意の パスで到達することができない メモリを割り当てられていることを知っています。これらのオブジェクトのすべて は、 自身を引き裂き、 の循環参照を破棄するように指示されます。それは、常に有益である -

ガベージコレクションの主な目的は、もちろん何も、時にはそれを避けることありませんが、彼らが作成したオブジェクトや使用のメモリ管理について心配するプログラマないをできるようにすることですガベージコレクションの仕組みについての大まかな考えがあります。

注意すべき点がいくつかあります。アップルの開発者サイトはsome guidelinesです。そこから2つの重要なもの:

  • 削除ステートメントを使用します。新しいステートメントを使用してオブジェクトを作成するときは、それをdeleteステートメントとペアにします。これにより、オブジェクトに関連付けられているすべてのメモリ(プロパティ名を含む)が確実にガベージコレクションできるようになります。 deleteステートメントについては、「オブジェクトの解放」を参照してください。
  • varキーワードを使用します。 varキーワードなしで作成された変数は、グローバルスコープで作成され、ガベージコレクションの対象にはなりません。メモリリークの可能性があります。

私は、これはAppleのサイトからなので、彼らはサファリに多少固有のかもしれませんが慣行は、(別のブラウザでは)すべてのJavaScriptエンジンに適用する必要があることを想像します。 (おそらく誰かがそれを明らかにすることができますか?)

希望があれば。

+3

アップルデベロッパサイトの+1リンク –

+4

リンクが壊れています。これは新しい場所のようです:http://developer.apple.com/safari/library/documentation/ScriptingAutomation/Conceptual/JSCodingGuide/Advanced/Advanced.html –

+0

@マーク:それを指摘してくれてありがとう。投稿が更新されます。 – Noldorin

1

JavaScriptガベージコレクションとは何ですか?ウェブプログラマがより良いコードを書くためには、JavaScriptのガベージコレクション、 について理解するためにthis

チェックは重要な何ですか?

Javascriptでは、メモリの割り当てと割り当て解除については気にしません。全体的な問題は、Javascriptインタプリタに求められています。 Javascriptでも漏れは可能ですが、通訳者のバグです。あなたは、このトピックに興味があるなら、あなたは読むことができるより多くで www.memorymanagement.org

+0

精巧? – tghw

+0

リンク先のアーティクル内のさまざまなメモリ管理システムのうち、JavaScriptで使用されているものはどれですか? _JavaScriptでは漏れは可能ですが、インタプリタのバグです。 "JSのプログラマーは、この問題全体を単純に無視できるわけではありません。例えば、かなりよく知られているJS <-> DOM循環参照の問題があります。あなたのJSコードで回避できる古いバージョンのIEです。また、JSが作業を終了させる方法はバグではなく、設計上の機能ですが、 "不適切に"クロージャを使用すると、意図したよりも大きなチャンクを張ることができます(私は 'emを使用しないという意味ではありません)。 – nnnnnn

+3

JavaScriptのメモリリークは獣です。シンプルな "カレッジプロジェクト"アプリケーションを作成している場合、心配する必要はありません。しかし、高性能のエンタープライズレベルのアプリケーションを作成するときは、JavaScriptによるメモリ管理が必須です。 – Doug

51

DOMオブジェクトが含まれる場合、循環参照に注意してください:

Memory leak patterns in JavaScript

は、オブジェクトへのアクティブな参照が存在しないときに、メモリにのみ再利用できることに注意してください。いくつかのJSエンジンは実際にどの変数が内部関数で参照されているのかをチェックせず、囲む関数のすべてのローカル変数を保持するだけなので、これはクロージャーとイベントハンドラーの一般的な落とし穴です。素朴なJSの実装は限りイベントハンドラは周りのあるようbigStringを収集することはできません

function init() { 
    var bigString = new Array(1000).join('xxx'); 
    var foo = document.getElementById('foo'); 
    foo.onclick = function() { 
     // this might create a closure over `bigString`, 
     // even if `bigString` isn't referenced anywhere! 
    }; 
} 

は、ここで簡単な例を示します。この問題を解決するには、bigString = nullinit()の末尾に設定します(deleteはローカル変数と関数の引数では機能しません)。deleteはオブジェクトからプロパティを削除し、変数オブジェクトにはアクセスできません。ローカル変数を削除しようとすると、ReferenceError!)。

メモリ消費を気にする場合は、できるだけ不要なクロージャを避けることをお勧めします。

+19

DOM循環参照のバグはJScript固有のもので、他のブラウザはIEに苦しんでいません。実際、ECMAScript仕様では、GCがそのようなサイクルを処理できる必要があることが明示されています。 -/ – olliej

+0

@olliej:[ECMAScript仕様](http: /www.ecma-international.org/publications/files/ECMA-ST/Ecma-262.pdf)。 –

+0

http://point.davidglasser.net/2013/06/27/surprising-javascript-memory-leak.html – Christoph

13

それは、あなたがいずれかの成分内のオブジェクトを作成し、そのオブジェクトのトラックを失った場合という意味のJScriptコンポーネント、であるとして、DOMのコンポーネントは、「ガベージコレクション」されたブログから

を取らグッド引用最終的には浄化されるだろう。例えば

:あなたは、その関数を呼び出すとき

function makeABigObject() { 
var bigArray = new Array(20000); 
} 

は、JScriptのコンポーネントは、関数内でアクセス可能である(bigArrayという名前の)オブジェクトを作成します。しかし関数が返ってくるとすぐに、bigArrayを参照する方法がないため、bigArrayの "追跡が失われる"ことになります。さて、JScriptのコンポーネントは、あなたがそれを見失ったことを認識しています。そのため、bigArrayはクリーンアップされ、そのメモリは再利用されます。同じ種類のものがDOMコンポーネントで動作します。 document.createElement('div')などと似ていると、DOMコンポーネントによってオブジェクトが作成されます。何らかの形でそのオブジェクトの追跡が失われると、DOMコンポーネントは関連オブジェクトをクリーンアップします。

13

私の知る限りは、JavaScriptのオブジェクトはゴミオブジェクトに残りの参照がないとき定期的に収集しています。自動的に行われるものですが、C++レベルでの動作の詳細については、WebKitまたはV8 source codeを参照してください。

一般的に考える必要はありませんしかし、古いブラウザでは、IE 5.5およびIE 6の初期バージョン、そしておそらく現在のバージョンと同様に、クロージャは未チェックのメモリを食べ終わるだろうと循環参照を作成します。あなたはDOMオブジェクトへのJavaScriptの参照、およびJavaScriptオブジェクトへ差し戻さDOMオブジェクトにオブジェクトを追加したとき、私は、クロージャについての意味特定のケースでは、それはでした。基本的には収集できない可能性があり、クラッシュを引き起こすためにループしたテストアプリでOSが不安定になることになります。実際には、これらのリークは通常小さいですが、コードをきれいに保つためには、DOMオブジェクトへのJavaScript参照を削除する必要があります。

通常、すぐにDE-参照にあなたがあなたが特にモバイルWeb開発では、それを行う必要があるものは何でも戻って受信して行っているJSONデータのような大きなオブジェクトを削除するキーワードを使用することをお勧めします。これにより、GCの次の掃引でそのオブジェクトが削除され、メモリが解放されます。再びアクセスしたり変異さ決してコンピュータサイエンス、ガベージコレクション(GC)で

+0

IEの新しいバージョンでJavaScript - > DOM - > JavaScript循環参照の問題が解決されていますか?もしそうなら、いつ?私はそれが構造的に非常に深く、修正されることはほとんどないと思った。何か情報源がありますか? – erikkallen

+0

ちょうど逸話的に。私は、標準モードで動作しているInternet Explorer 8の狂ったリークに気付きません。壊れたモードではありません。私は私の反応を調整します。 –

+1

@erikkallen:古いものは、それが不可能相互に参照するオブジェクトのペアをGCに作られた非常に単純なガベージコレクションのアルゴリズムを、使用していたとして、はい、GCのバグは、IEのバージョン8+で修正されています。より新しい 'マークアンドスイープ(mark-and-sweep) 'スタイルアルゴリズム[これを世話する](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Memory_Management)。 –

3

」自動メモリ管理の一形態である。ガベージコレクタ、または単にコレクタ、ごみを再利用しようとする、またはオブジェクトによって使用されるメモリアプリケーションによって。

すべてのJavaScriptエンジンには、それぞれ独自のガベージコレクタがあり、それぞれが異なる場合があります。ほとんどの時間は、彼らは彼らがやるべきことをするだけなので、彼らに対処する必要はありません。より良いコードを書く

は、主にあなたがプログラミングの原則、言語や特定の実装を知っていますかどのように良いに依存します。 Windows上で

1

あなたはメモリリークを見つけるか、またはあなたの自由MEMルーチン作品かどうかを確認するためにDrip.exeを使用することができます。

これは本当に簡単です。ウェブサイトのURLを入力するだけで、統合されたIEレンダラのメモリ消費量がわかります。リフレッシュした後、メモリが増えた場合は、Webページのどこかでメモリリークが発生しています。しかしこれは、メモリを解放するためのルーチンがIEで動作するかどうかを確認するのにも非常に便利です。

6

ガベージコレクション(GC)は、不要になったオブジェクトを削除することで自動メモリ管理の一種です。

メモリを搭載した任意のプロセスの契約は、次の手順を実行します。

1 - あなたは

2を必要とするあなたの記憶領域を割り当てる - いくつかの処理

3を行う - 無料

があり、このメモリ空間をどのオブジェクトがもはや必要でないことを検出するために使用される2つの主要なアルゴリズム。

参照カウントガーベジコレクション:このアルゴリズムは、オブジェクトが削除されます、「オブジェクトが他のオブジェクトがそれに参照していない」に「オブジェクトはもう必要ありません」の定義を減らす場合は、それ

への基準点ありません

マークアンドスイープアルゴリズム:各オブジェクトをルートソースに接続します。どのオブジェクトもルートまたは他のオブジェクトに接続しません。このオブジェクトは削除されます。

現在のところ、最新のブラウザでは2番目のアルゴリズムを使用しています。

+1

そしてこのソースを追加するには、MDN:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Memory_Managementを参照してください。 – Xenos

関連する問題