11

この質問は以前にもあったと思いましたが、ここでは見つかりませんでした...

SWIG を使用して C++ クラスの JNI ラッパーを作成しました。Java がクラスの finalize() を呼び出すことがないように見えることを除いて、すべてがうまく機能するため、クラスのデストラクタが呼び出されることはありません。クラスのデストラクタは最終的なファイル I/O を実行するため、残念ながら、これは単なるマイナー メモリ リークではありません。

Google で検索すると、Java を強制的に GC にしてオブジェクトを破棄する方法はないようです。真実?

SWIG ファイルを操作して C++ デストラクタを呼び出す Java 関数を作成できることはわかっていますが、このクラスは複数の異なるプラットフォーム/言語のエンド ユーザーによって使用されているため、Java のみのクラスを追加すると、私たちの技術に矛盾が生じます。作家は気に入らないでしょう。

4

5 に答える 5

8

System.gc()でGCを強制することはできません。また、たとえば、アプリが短時間しか実行されず、ファイナライザーがまったく実行されない場合(JVMが終了時に実行されない場合)、GCが実行されることは保証されません。close()やdestroy()など、クラスの関数を作成する必要があります。このクラスのインスタンスの使用が終了したら、できればfinallyブロックから呼び出します。


MyClass x = null;
try{
    x = new MyClass();
    x.work();
} finally {
    if (x!=null)
        x.close();
}
于 2009-06-18T19:50:57.483 に答える
7

私の意見では、Java ファイナライザはほとんど役に立たず、C++ デストラクタの代わりにはなりません。残念ながら、Java には C++ RAII に代わるものはありません。

Java のファイナライズを強制しようとしないでください。何でも使い終わったら、それを処分するすべての関数。できることはそれだけです。

于 2009-06-18T19:45:36.573 に答える
4

finalize特定の時間に実行するメソッドのコードに依存している場合は、アプローチを再検討する必要があります。ここでの問題はfinalize、オブジェクトがいつガベージ コレクションされるかわからないため、いつ JVM によって呼び出されるかわからないことです。

クラスは他のプロジェクトで再利用されるため、考慮すべきことの 1 つは、エンドユーザーがクラスのインスタンスを使用して、それが収集されなかったり、ガベージ コレクションが実行されたりする可能性があることです。クラスのインスタンスへの静的参照を作成するなど、可能性は低いです。Java オブジェクトに関連付けられた C++ クラスのインスタンスが使用しているリソースが適切に解放されるようにするには 、 closeorメソッドを作成するのが最も安全な方法だと思います。destroy

再利用が懸念されるため、次のように、C++ デストラクタでリソースが解放されているかどうかを確認し、解放されていない場合は同じコードを呼び出すことができます。

class MyThing {
  public:
    void close();
    ~MyThing();

  private:
    bool released = false;
};

void
MyThing::close() {
  // close logic here
  this->released = true;
}

MyThing::~MyThing() {
  if (!released) {
    this->close();
  }
}

この方法では、既存の C++ コードをあまり変更する必要がなく、JNI を介して実行されるネイティブ コードのコンテキストでリソースが決定論的な方法で確実に解放されるようにすることができます。

于 2009-06-18T21:15:26.017 に答える
2

SWIG で作成されたコードをさらに調べたところ、SWIG の人々は実際には既にこれに対処していることがわかります。彼らは delete() 関数を追加しています。プログラマーと GC の両方がオブジェクトを削除する可能性も十分に考慮されているようです。

于 2009-06-19T13:15:00.557 に答える
-1

このような問題が、C# が確定的なファイナライズにIDisposableパターンを選択した理由です。

同じパターンに従って、Java ユーザーに合わせて調整することをお勧めします。

C++ クラスで、リソースを破棄する別のパブリック メソッドを作成します。それを閉じる、または処分する、または何かと呼びます。

C++ デストラクタにパブリック メソッドを呼び出してもらい、メモリ リークを避けるためにメソッドを呼び出す必要があることを C++ クラスのマネージ/GC ユーザーに伝えます。

于 2009-06-18T20:02:50.220 に答える