問題タブ [finalizer]
For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.
.net - ファイナライザーから RCW を呼び出すのは安全ですか?
COM サーバーを呼び出してメモリを割り当てるマネージ オブジェクトがあります。マネージ オブジェクトは、メモリ リークを回避するために、マネージ オブジェクトがなくなる前にそのメモリを解放するために、再度 COM サーバーを呼び出す必要があります。このオブジェクトIDisposable
は、正しいメモリ解放 COM 呼び出しが確実に行われるようにするために実装されます。
Dispose
メソッドが呼び出されない場合は、オブジェクトのファイナライザーにメモリを解放してもらいたいです。問題は、ファイナライズの規則では、参照にアクセスしてはならないということです。これは、他のどのオブジェクトが既に GC および/またはファイナライズされているかわからないためです。これにより、タッチ可能なオブジェクトの状態はフィールドのみになります (ハンドルが最も一般的です)。
しかし、COM サーバーを呼び出すには、フィールドに格納する Cookie のメモリを解放するために、ランタイム呼び出し可能ラッパー (RCW) を経由する必要があります。 そのRCWはファイナライザーから安全に呼び出すことができますか(この時点でGCまたはファイナライズされていないことが保証されていますか)?
ファイナライズに慣れていない方のために説明すると、ファイナライザー スレッドはマネージド アプリドメインの実行中にバックグラウンドで実行されますが、参照に触れることは理論的には問題ありません。参照関係の順序で。これにより、ファイナライザーから触れても安全であると想定できるものが制限されます。管理対象オブジェクトへの参照は、参照が null でない場合でも、「不良」(収集されたメモリ) である可能性があります。
更新:試してみたところ、これが得られました:
タイプ 'System.Runtime.InteropServices.InvalidComObjectException' の未処理の例外が myassembly.dll で発生しました
追加情報: 基礎となる RCW から分離された COM オブジェクトは使用できません。
.net - ファイナライザーと IDisposable のテスト
問題は、ファイナライズが呼び出されたときにオブジェクトがリソースを破棄するという事実をどのようにテストできるかです。クラスのコード:
最初にテストする方法を見つけたいので、今は Dispose/Finalize の正しい実装は気にしないことに注意してください。この段階では、Dispose/Finalize ウェアが呼び出された場合に HasBeenDisposedが true に設定されると想定するだけで十分です。
私が書いた実際のテストは次のようになります:
UPDATED WITH WEAKREFERENCE :
または私が好きなコード(ADDED AFTER UPDATE):
このテストは失敗します(PASSES AFTER UPDATE)が、次のことを観察します(UPDATED):
- GC.WaitForPendingFinalizers() は、スレッドを中断し、インスタンスをoでファイナライズしますが、ルート化されていない場合のみです。それにNULLを割り当て、WeakReferenceを使用してファイナライズ後に取得しました。
- oがインスタンスを保持していない場合、ファイナライズ (デストラクタ) コードは正しいポイントで実行されます。
それで、これをテストする正しい方法は何ですか。何が恋しいですか?
GCがそれを収集できないのは変数oだと思います。
更新:はい、それは問題です。代わりに WeakReference を使用する必要がありました。
java - SoftReference指示対象を適切に完成させる
検索ハンドルオブジェクトを開いたままにしておくと、クエリキャッシュに役立つ検索ライブラリを使用しています。時間の経過とともに、キャッシュが肥大化する傾向があり(数百メガバイトで成長し続ける)、OOMが起動し始めました。このキャッシュの制限を強制したり、使用できるメモリの量を計画したりする方法はありません。そのため、 Xmxの制限を増やしましたが、これは問題の一時的な解決策にすぎません。
最終的に、私はこのオブジェクトをの指示対象にすることを考えていますjava.lang.ref.SoftReference
。したがって、システムの空きメモリが不足すると、オブジェクトが解放され、オンデマンドで新しいオブジェクトが作成されます。これにより、新たに開始した後の速度がいくらか低下しますが、これはOOMを押すよりもはるかに優れた代替手段です。
SoftReferencesについて私が目にする唯一の問題は、指示対象を確定するためのクリーンな方法がないことです。私の場合、検索ハンドルを破棄する前に閉じる必要があります。そうしないと、システムでファイル記述子が不足する可能性があります。明らかに、このハンドルを別のオブジェクトにラップし、ファイナライザーを記述して(または、ReferenceQueue / PhantomReferenceにフックして)、手放すことができます。しかし、ねえ、この惑星のすべての記事は、ファイナライザーの使用、特にファイルハンドルを解放するためのファイナライザーの使用を推奨していません(たとえば、 Effective Java ed。II、27ページ)。
だから私は少し戸惑っています。これらのアドバイスをすべて慎重に無視して続行する必要があります。そうでなければ、他の実行可能な選択肢はありますか?前もって感謝します。
編集#1:トムホーティンによって提案されたようにいくつかのコードをテストした後、以下のテキストが追加されました。私には、提案が機能していないか、何かが足りないように見えます。コードは次のとおりです。
上記のスニペットを-Xmx10m
(上記のコードのように)SoftReferencesを使用して実行すると、大量のis null :(
印刷が行われます。しかし、コードをMyReference
(MyReferenceで2行のコメントを解除し、SoftReferenceでコメントアウトする)に置き換えると、常にOOMになります。
アドバイスから理解したように、内部にハードリファレンスがあるからといって、MyReference
オブジェクトが当たるのを防ぐことはできませんReferenceQueue
よね?
c# - Object.Finalize() オーバーライドと GC.Collect()
Object.Finalize() をオーバーライドするクラスが存在する場合の GC.Collect() の動作を理解できないようです。これは私の基本コードです:
予想に反して、プログラムの終了時にのみコンソール出力を取得し、終了後は取得しませんGC.WaitForPendingFinalizers()
c# - Thread が IDisposable を実装しないのはなぜですか?
System.Threading.Thread はファイナライザーを実装していますが、IDisposable を実装していないことに気付きました。推奨される方法は、ファイナライザーが実装されている場合は常に IDisposable を実装することです。Jeffrey Richterは、このガイドラインは「非常に重要であり、常に例外なく従うべきである」と書いています。
では、なぜ Thread は IDisposable を実装しないのでしょうか? IDisposable の実装は、スレッドのファイナライズ可能なリソースの決定論的なクリーンアップを可能にする非破壊的な変更になるようです。
関連する質問: スレッドはファイナライズ可能であるため、実行中にスレッドがファイナライズされないように、実行中のスレッドへの参照を保持する必要がありますか?
recursion - Statefinalization/initialization アクティビティはリーフ ステートでのみ実行されます
Windows ステート マシンのワークフローでエンド ユーザーと通信できるようにしようとしています。StateActivity 内で実装しようとしている一般的なパターンは次のとおりです。
StateInitializationActivity: 質問に対する回答を要求するメッセージをユーザーに送信します (例: 「このドキュメントを承認しますか?」)。...
...EventDrivenActivity: ユーザーが送信した回答を処理する
StateFinalizationActivity: キャンセル メッセージ (例: 「このドキュメントを承認しますか?」)文書は撤回され、承認は必要ありません)
StateActivity が「リーフ状態」(つまり、子状態がない) の場合、これはすべて正常に機能します。ただし、状態の再帰合成を使用したい場合は機能しません。非リーフ ステートの場合、StateInitialization と StateFinalization は実行されません (この動作は、Reflector を使用して StateActivity ソース コードを調べて確認しました)。EventDrivenActivity はまだリッスンしていますが、エンド ユーザーは何が起こっているのかわかりません。
StateInitialization については、これを回避する 1 つの方法は、EventDrivenActivity とゼロ遅延タイマーに置き換えることだと思いました。StateFinalization をどうするか悩んでいます。
だから - リーフ以外の状態であっても、状態のファイナライズアクティビティを常に実行する方法について誰か考えがありますか?
c# - JavaとC#にファイナライザーがあるのはなぜですか?
javaやc#などの言語にファイナライザーがある理由がよくわかりません。AFAIK、彼ら:
- 実行が保証されていません(Javaで)
- それらが実行される場合、問題のオブジェクトがファイナライズの候補になった後、任意の時間実行される可能性があります
- そして(少なくともJavaでは)、クラスに固執することすら驚くほど大きなパフォーマンスヒットを被ります。
では、なぜそれらが追加されたのでしょうか。友人に聞いたところ、「DB接続などをクリーンアップする機会があればいいのに」とつぶやいたのですが、これは悪い習慣だと思います。最後の防衛線としてさえ、なぜあなたは何かのために上記の特性を持つ何かに頼る必要がありますか?特に、似たようなものがAPIに設計されている場合、そのAPIは存在しなくなって笑われるでしょう。
c# - デストラクタとファイナライザの違いは?
注意: この質問は、「デストラクタ」と「ファイナライザ」という言葉の用語の違いと、それらの正しい使用法に関するものです。C# および C++/CLI での使用例を示して、なぜこの質問をするのかを示しただけです。C# と CLR の両方でどのように実装されているかはよく知っていますが、用語の正しい使い方について質問しています。
C# の世界では、「デストラクタ」と「ファイナライザ」という用語はほぼ同じ意味で使用されているように思われます。これは、C# の仕様では「デストラクタ」という言葉を使用して非決定論的クリーンアップ機能が記述されているためだと思われますが、CLR のドキュメントでは常に「ファイナライザー」という言葉なので、C# の領域内では同じことを意味します。
ただし、C++/CLI 仕様では、この 2 つが区別されています。決定論的および非決定論的なクリーンアップの両方が可能であり、決定論的な機能には「デストラクタ」という用語を使用し、非決定論的な機能には「ファイナライザ」という用語を使用します。
ファイナライザーは、非決定的なクリーンアップを提供します。ファイナライザは、通常、デストラクタが実行されなかったオブジェクトに対して、ガベージ コレクション中に実行される「ラストチャンス」関数です。
さらに、ウィキペディアのデストラクタとファイナライザの説明は、デストラクタとファイナライザが別の概念であることを示しており、決定論に関する C++/CLI 仕様の用語の使用をサポートしています。
デストラクタとは異なり、ファイナライザは決定論的ではありません。プログラムがオブジェクトを明示的に解放すると、デストラクタが実行されます。対照的に、ファイナライザーは、内部ガベージ コレクション システムがオブジェクトを解放するときに実行されます。
質問:
コンピュータサイエンスの観点から、「デストラクタ」と「ファイナライザ」の間に明確に定義された違いはありますか、それとも用語は文脈上でのみ定義できるものですか?
明確に定義された違いがある場合、なぜ C# 仕様は「間違った」用語を使用するのでしょうか?
c# - ファイナライザで AppDomain.Unload() エラーが発生するのはなぜですか?
サンプルコードは次のとおりです。
オブジェクトの存続期間にわたって使用されるコンストラクターで AppDomain を作成するクラスがあります。AppDomain を適切にクリーンアップしたいので、ファイナライザーで Unload を呼び出すことにしました。残念ながら、これにより CannotUnloadAppDomainException がスローされます。AppDomain.Unloadの MSDN ドキュメントには次のように記載されています。
場合によっては、Unload を呼び出すと、すぐに CannotUnloadAppDomainException が発生します。
どうしてこれなの?メンバー変数「ドメイン」は既にクリーンアップされていますか? そのクリーンアップには、AppDomain のアンロードが自動的に含まれますか? それとも、アクセスできない方法でまだ存在しますか? 私がすべきことはありますか、それともファイナライザーを安全にダンプできますか? (プロセスでオブジェクトが完全にクリーンアップされている限り、GC がいつオブジェクトを削除するかはあまり気にしません。)
.net - デストラクタで Excel オブジェクトを解放する
Microsoft.Interropt.Excel DLL を使用して Excel クラスを作成しています。すべての機能を終了しましたが、デストラクタにエラーがあります。すべての変更をファイルに保存し、すべてのソースをリリースしたいと考えています。私はデストラクタでそれらすべてをしたい。しかし、私のデストラクタでは、Excel.ApplicationClass、Workbook、および Worksheet オブジェクトが例外で満たされ、「基になる RCW から分離された COM オブジェクトは使用できません」というメッセージが表示されます。ワークブックまたはワークシート オブジェクトにアクセスできないため、何も保存できず、何も閉じられません。
Destructor でクラスのプライベート メンバーにアクセスできませんか?