2009-06-18 21 views
9

フォースJavaは私のCを呼び出しますC++クラス。 Javaがクラスのfinalize()を呼び出すように見えないことを除いて、すべての作品は素晴らしいので、クラスのデストラクタは決して呼び出されません。クラスのデストラクタは最終的なファイルI/Oを行います。残念ながら、これはちょっとしたメモリリークではありません。私は周りのJNIラッパーを作成するためにSWIGを使用しました</p> <p>...私はこの質問は前に頼まれていたであろうと思ったが、私はここでそれを見つけることができませんでした++デストラクタ(JNI)

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

私はSWIGファイルを操作してC++デストラクタを呼び出すJava関数を作成することができますが、このクラスはいくつかの異なるプラットフォーム/言語のエンドユーザによって使用されるため、Javaのみを追加すると私たちの技術者が好きではないという不一致があります。

答えて

7

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


MyClass x = null; 
try{ 
    x = new MyClass(); 
    x.work(); 
} finally { 
    if (x!=null) 
     x.close(); 
} 
5

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

Javaのファイナライズを強制しないでください。あなたが何とかしているとき、それを処分するすべての機能。それだけであなたができることです。

0

の問題は、C#は、決定論的ファイナライズのためIDisposableパターンを選んだ理由です。

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

あなたのC++クラスでは、あなたのリソースを処分する別の公開メソッドを作成します。それを閉鎖するか、処分するか、何かを呼んでください。

あなたのC++デストラクタにパブリックメソッドを呼び出し、メモリリークを避けるためにメソッドを呼び出さなければならないことをC/C++クラスのmanaged/GCユーザに伝えます。

5

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

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

再使用が懸念されるので、あなたは彼らがそうのように、していなかった場合は、リソースが解放されていたと同じコードを呼び出すためにかどうかを確認するために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を介して実行されるネイティブコードのコンテキストで、リソースが確定的にリリースされるようにすることができます。

3

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

関連する問題

 関連する問題