JavaScriptのメモリリリース問題詳細

4416 ワード

本論文では、JavaScript及びIEブラウザのメモリ管理とリリースのタイミングと方法について詳しく説明します.
メモリのリリース例
 
  
<br> <!-- <br> strTest = "1"; <br> for ( var i = 0; i < 25; i ++ ) <br> { <br> strTest += strTest; <br> } <br> alert(strTest); <br> delete strTest; <br> CollectGarbage(); <br> //--> <br>
CollectGarbageは、IEの特有の属性で、メモリをリリースするためのものです.使用方法は、その変数や参照対象をnullまたはdeleteに設定して、リリース動作を行っています.
CollectGarbageを作る前に、明確にしなければならない二つの必須条件:
参照-オブジェクトは、そのコンテキスト環境以外では無効になります.全体のオブジェクトが執用されていない(引用されていない)場合は無効になります.
 
  
//---------------------------------------------------------
// JavaScript
//---------------------------------------------------------
function testObject() {
var _obj1 = new Object();
}
function testObject2() {
var _obj2 = new Object();
return _obj2;
}
// 1
testObject();
// 2
testObject2()
// 3
var obj3 = testObject2();
obj3 = null;
// 4
var obj4 = testObject2();
var arr = [obj4];
obj3 = null;
arr = [];
この4つの例では、−「例1」は、関数testObject()において構築されている.Obj 1ですが、関数が終了すると、関数のコンテキストを離れてしまいます.obj 1が失効しました
-「例2」では、testObject 2()にもオブジェクトが1つ構成されています.obj 2は、オブジェクトに「関数外」のコンテキスト環境がありますが、関数の戻り値は他の変数に「保持」されていません.obj 2もすぐに失効しました.
-「例3」では、testObject 2()で構成されている_Obj 2は外部の変数Obj 3によって使用されました.このとき、「Obj 3=null」という行のコードが有効になるまで、_obj 2は引用関係が消滅して無効になります.
-例3と同じ理由で、「例4」の_obj 2は「arr=[]」の行のコードの後で無効になります.
ただし、対象の「失効」は「釈放」を待たない.JavaScript実行環境の内部では、「オブジェクトはいつリリースされるか」をユーザーに確実に伝える方法はありません.これはJavaScriptのメモリ回収メカニズムに依存しています.――このような戦略は.NETにおける回収メカニズムと同様である.
前のExcel操作例コードでは、オブジェクトの所有者、つまり「EXCEL.EXE」というプロセスは、「ActiveX Objectインスタンスのリリース」後にのみ発生します.ファイルのロック、およびオペレーティングシステムの権限証明はプロセスに関連しています.したがって、オブジェクトが「無効」であって、「リリース」ではない場合、他のプロセスがファイルを処理したり、オペレーティングシステムの権限を引用したりするときに問題が発生します.
――JavaScriptやCOMの仕組みのBUGだという人もいます.これは独立の問題ではなく、OS、IEとJavaScriptの間の複雑な関係によるものです.
Microsoftはこのような問題を解決するための方策を公開した.メモリ回収プロセスを積極的に起動する.
(マイクロソフトの)JScriptでは、Collect Garbage(通常はGCプロセスと略称する)プロセスが提供されており、GCプロセスは現在のIEの中の「無効なオブジェクトの失敗例」を整理するために使用され、オブジェクトの解析プロセスを呼び出します.
上記の例では、GCプロセスを呼び出すコードは:
 
  
//---------------------------------------------------------
// ActiveX Object ,GC
//---------------------------------------------------------
function writeXLS() {
//( ...)
excel.Quit();
excel = null;
setTimeout(CollectGarbage, 1);
}
最初の行のコードはexcel.Quit()メソッドを呼び出してexcelプロセスを中止して終了させます.この時、JavaScript環境はexcelオブジェクトのインスタンスを持っていますので、excelプロセスは実際に中止されません.
2行目のコードは、excelをnullとし、対象の参照をクリアすることで、対象を「無効」にします.しかし、オブジェクトはまだ関数コンテキストにありますので、GCプロセスを直接呼び出すと、オブジェクトはまだ整理されません.
第3行コードはsetTimeout()を使用してCollectGarbage関数を呼び出し、時間間隔は'1'に設定されているが、GCプロセスはwriteXLS()関数が実行された後に発生する.このようにexcelオブジェクトは、「GCによってクリアできる」という二つの条件を満たしています.
GCプロセスの使用は、ActiveX Objectを使用したJS環境において有効である.いくつかの潜在的なActiveXObjectはXML、VML、OWC(Office Web Compone)、flashを含んでいます.JSのVallyも含まれています.この点から、ajaxアーキテクチャはXMLHTTPを採用し、同時に「ページを切り替えない」という特性を満たすため、適切な時にGCプロセスをアクティブに起動することで、より効率的なUI体験が得られる.
実際にGCプロセスを使っても、前述のエクセル問題は完全に解決されません.IEはまた、権限証明書をキャッシュしているからです.ページの権限を更新させる唯一の方法は、「新しいページに切り替える」しかありません.
そのため、前述のSPSプロジェクトでは、私が採用した方法はGCではなく、次のようなコードです.
 
  
//---------------------------------------------------------
// ActiveX Object
//---------------------------------------------------------
function writeXLS() {
//( ...)
excel.Quit();
excel = null;
// IE call Excel BUG, MSDN :
// setTimeout(CollectGarbage, 1);
// ( ) , SaveAs()
// .
location.reload();
}
delete演算子のマニュアル上の説明参照は、オブジェクトから属性を削除するか、配列から要素を削除します.
delete expression
expressionパラメータは有効なJScript式であり、通常は属性名または配列要素である.
説明
expressionの結果がオブジェクトであり、expressionで指定された属性が存在し、オブジェクトが削除されることを許可しない場合はfalseに戻ります.
他のすべての場合、trueに戻ります.
最後に、GCの補足説明について:IEフォームが最小化されると、IEはCollect Garbage()関数をアクティブに起動する.これにより、IEウィンドウが最小化された後、メモリ占有率が著しく改善される.