2012-01-09 10 views
5

プロジェクトでは、追加のクラスを持つ添付ファイルが付属するユーザースクリプトを実行する方法が必要です。単体テストGCはどのようにしてできますか?

普通のスクリプトが何かを残していないことを確認するためにいくつかのテストを書いてみたいとき、私の選択肢は何ですか?

私は具体的に知っておく必要があります。添付されたJARのすべてのクラスがアンロードされていますか?

注:私は、1.0から7までのすべてのJavaバージョンで機能する100%超防水ソリューションを探しているわけではありません。今は「わかりません」よりも優れている必要があります。

+0

を呼び出して、スクリプトを実行し、そのJARをロードするために使用ClassLoaderWeakReferenceを作成したいですか?そのインスタンスがGCされることを意味しますか?つまり、ユーザースクリプトのコードとライブラリにメモリリークはありませんか?それらに新しいクラスローダーをロードしていますか? –

+0

はい。私が望むのは、GCに "このインスタンスを今GCできますか?"と尋ねる方法です。あるいは、 '' foo'をインスタンス化するために参照がいくつあるのかを教えてください。 " –

答えて

3

ロードされたjarが特定のクラスローダーによってロードされていることを確認し、そのクラスローダーを破棄する(すべてのオブジェクトを破棄した後)ことをお勧めします。

アンロードをユニットテストする場合、このオプションを使用する場合は、テストフレームワークとカスタマイズされたクラスローダーを拡張して、「クラスローダをオンデマンドで作成」フラグを持たせる必要があります。次に、フラグをオンにしてクラスを一度ロードし、クラスローダーを破棄し、フラグをオフにしてクラスを再度ロードしようとします。クラスが本当に到達可能でない場合、2回目の試みはクラスが見つからない例外をスローする必要があります。その後、ユニットテストをラップして例外に該当する場合は合格にし、2回目のロード試行後にラインに当たった場合は失敗します。

純粋なJavaツールを使用するように設定されている場合は、OSGiコンテナを考慮する必要があります。確立されたOSGiコンテナ実装のほとんどは、明示的にクラスのアンロードをテストします。

+0

+1は2番目のオプションです。100%(これは私が必要としているとは限りませんが)確実であるためには、スクリプトがスレッドを作成しなかったことを保証するために、セキュリティマネージャーを使ってクラスローダーを実行する必要があります。 –

+0

@Sean Reilly、ありがとう。他のオプションはノイズになりましたので、メッセージを上部に近づけました。 –

+0

問題のポイントは、Aaronが最初の段落で説明していることをすでに行っているようですが、Javaオブジェクトを明示的に破棄できないため、暗黙的に実際に起こっているかどうか、または漏れがあるかどうかを確認する方法が必要です。 –

3

私はこれをユニットテストしようとしません。代わりに、-XX:-TraceClassUnloadingを指定してJVMを実行し、問題のクラスがトレース出力に表示されるかどうかを調べます。

1

これは、スクリプトの実行方法によって異なります。彼らはアプリケーションの残りのクラスにアクセスできますか?

Javaでメモリをリークする典型的な方法は、静的な参照を持つことです。静的参照は、それを含むクラスのClassLoader内でのみ静的です。したがって、自分で管理するClassLoaderを使用してユーザースクリプトを読み込んだ場合(とにかくこれを行う必要があります)、内部の参照(静的または非静的)は、クラスローダー自体がすぐにGC用に適格になります。

これを回避する唯一の方法は、自分のオブジェクトの1つに参照を追加することです。そのため、公開するAPIには非常に注意する必要があります。別の方法は、別のClassLoaderのクラスのクラスへの静的な参照を作成するかどうかです。

これについてのテストを完全に自動化する方法はありません。しかし、まともなプロファイラでクラスをアンロードすることができると思います。

2

テストするもののように、ホーススクリプトにはclassloader leakが含まれていないようです。これを行うには

、私は彼らがアンロードされるだろう、なぜSystem.gc()、その後assertNull(reference.get())

+0

おそらくJARごとにURLClassLoaderのインスタンスを作成し、それを使用してクラスをロードする方法もあります。一度やり終えたらそれをゴミ箱にセットしてください。 – aishwarya

+1

@aishwarya:それはまったく「代替」ではありません。 Javaオブジェクトを「ゴミ箱」にすることはできません。参照をnullに設定するだけでは、他の参照がない場合にオブジェクトをガベージコレクションできます。私が記述しているのは、オブジェクトが実際にガベージコレクトされたことをテストする方法です。クラスローダーは、クラスローダーとそれを介してロードされたすべてのクラスがガベージコレクションされないようにするために、コレクションsomwhereに隠されたロードされたクラスの1つのオブジェクトへの参照が1つで十分であるため、 –

関連する問題