関連付けられたJavascriptオブジェクトがV8でガベージコレクションされる場合、ラップされたC ++オブジェクトをどのように解放しますか?
-
05-07-2019 - |
質問
V8のドキュメントでは、 C ++オブジェクトをラップするJavascriptオブジェクトの作成方法。 Javascriptオブジェクトは、C ++オブジェクトインスタンスへのポインターを保持します。私の質問は、ヒープにC ++オブジェクトを作成するとしましょう。Javascriptオブジェクトがgcによって収集されると、どのようにして通知を取得できますか。そうすると、ヒープに割り当てられたC ++オブジェクトを解放できますか?
解決
トリックは、Persistent
ハンドルを作成することです(リンク先APIリファレンスからの2番目の箇条書き:<!> quot; MakeWeak()
ハンドルはスタックに保持されず、具体的に削除した場合にのみ削除されます。 ...複数の関数呼び出しでオブジェクトへの参照を保持する必要がある場合、またはハンドルの有効期間がC ++スコープに対応していない場合、永続ハンドルを使用します。<!> quot;)、およびその上でPersistent::MakeWeak
を呼び出し、必要なクリーンアップを実行するコールバック関数を渡す<!> quot;-つまり、すべての<!> quot; regular <!> quot;ハンドルがスコープ外になり、ガベージコレクターがオブジェクトを削除しようとしている場合)。
WeakReferenceCallback
メソッドのシグネチャは次のとおりです。
void MakeWeak(void* parameters, WeakReferenceCallback callback);
MakeWeak
は、2つのパラメーターを取る関数へのポインターとして定義されています。
typedef void (*WeakReferenceCallback)(Persistent<Object> object,
void* parameter);
これらは、V8でパブリックAPIとして配布されるv8.hヘッダーファイルに含まれています。
Persistent<Object>
に渡す関数は、コールバックとして呼び出されたときに渡されるvoid* parameter
オブジェクトパラメーターをクリーンアップする必要があります。 <=>パラメーターは無視できます(または、<=>は、クリーンアップが必要なオブジェクトを保持するC ++構造体を指すことができます):
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 ++オブジェクト)への参照を保持できる場合、そのリソースをできるだけ早く解放する 'close'メソッドを提供する必要があります。オブジェクトを破棄する価値があるとGCが判断するまで待機します。
C ++オブジェクトがメモリを大量に消費し、ガベージコレクションされたオブジェクトが単なる参照である場合、さらに悪化します。数千のオブジェクトを割り当てる場合があり、GCはコレクションをトリガーするには不十分な数KBの小さなオブジェクトしか認識しません。 C ++側は数十メガバイトの古いオブジェクトに苦労しています。
(オブジェクトまたは関数の)閉じたスコープですべての作業を行います。 その後、スコープから外れたときにC ++オブジェクトを安全に削除できます。 GCは、ポイントされたオブジェクトの存在についてポインターをチェックしません。