V8 のドキュメントでは、C++ オブジェクトをラップする Javascript オブジェクトを作成する方法について説明しています。Javascript オブジェクトは、C++ オブジェクト インスタンスへのポインターを保持します。私の質問は、ヒープ上に C++ オブジェクトを作成するとしましょう。Javascript オブジェクトが gc によって収集されたときに通知を受け取るにはどうすればよいので、ヒープに割り当てられた C++ オブジェクトを解放できますか?
3 に答える
秘訣は、Persistent
ハンドルを作成することです(リンク先のAPIリファレンスからの2番目の箇条書き: "Persistent
ハンドルはスタックに保持されず、特に削除した場合にのみ削除されます。...保持する必要がある場合は、永続ハンドルを使用してください。複数の関数呼び出しのオブジェクトへの参照、またはハンドルの有効期間がC++スコープに対応していない場合。")、MakeWeak()
必要なクリーンアップを実行するコールバック関数を渡してオブジェクトを呼び出します("永続的なハンドルを弱くすることができます。を使用しPersistent::MakeWeak
て、オブジェクトへの唯一の参照が弱い永続ハンドルからのものである場合に、ガベージコレクターからのコールバックをトリガーします。」-つまり、すべての「通常の」ハンドルがスコープ外になり、ガベージコレクターが削除しようとしている場合物体)。
Persistent::MakeWeak
メソッドシグネチャは次のとおりです。
void MakeWeak(void* parameters, WeakReferenceCallback callback);
ここWeakReferenceCallback
で、は2つのパラメーターをとる関数へのポインターとして定義されます。
typedef void (*WeakReferenceCallback)(Persistent<Object> object,
void* parameter);
これらは、パブリックAPIとしてV8とともに配布されるv8.hヘッダーファイルにあります。
渡す関数は、コールバックとして呼び出されたときに渡されるオブジェクトパラメーターMakeWeak
をクリーンアップする必要があります。パラメータは無視できます(または、Persistent<Object>
クリーンアップが必要なオブジェクトを保持するC ++構造を指すことができます)。void* parameter
void* parameter
void CleanupV8Point(Persistent<Object> object, void*)
{
// do whatever cleanup on object that you're looking for
object.destroyCppObjects();
}
Parameter<ObjectTemplate> my_obj(ObjectTemplate::New());
// when the Javascript part of my_obj is about to be collected
// we'll have V8 call CleanupV8Point(my_obj)
my_obj.MakeWeak(NULL, &CleanupV8Point);
すべての作業を (オブジェクトまたは関数の) クローズド スコープで行います。その後、スコープ外に出たときに C++ オブジェクトを安全に削除できます。GC は、指定されたオブジェクトの存在についてポインターをチェックしません。
一般に、ガベージコレクションされた言語が言語エンジンの外部のリソース (ファイル、ソケット、またはあなたの場合は C++ オブジェクト) への参照を保持できる場合、そのリソースをできるだけ早く解放するために「close」メソッドを提供する必要があります。 GC は、オブジェクトを破棄する価値があると考えています。
C++ オブジェクトがメモリを大量に消費し、ガベージ コレクションされたオブジェクトが単なる参照である場合は、さらに悪化します。何千ものオブジェクトを割り当てる可能性がありますが、GC は数 KB の小さなオブジェクトしか認識せず、コレクションをトリガーするのに十分ではありません。一方、C++ 側は数十メガバイトの古いオブジェクトに苦労しています。