2013-06-26 7 views
5

私はクラスを作成するためにJavassistを使用します。そして、テストスイート、第二の試験は、同じクラスを作成しようとすると、クラスが凍結されているので、それはpool.makeClass(...)で失敗した(すなわち、すでにtoClass()を使用して作成。Javassist:クラスの再作成 - 最初に削除するか、または除外()して変更しますか?

に最初のテストがすべき、理想的には?これを克服する方法は何何とかクラスを削除する - おそらくクラスローダーからアンロード - 。しかし、私はin JLSを読んで、アンロード操作は信頼できません

ので、おそらくこの問題を回避するには、それが存在するかどうかをクラスの作成コードをチェックインすることであり、それがない場合には、defrost()すべてのメンバーなどを削除して再作成してください。

他のアイデア?

また、Javassistを使用して確実にクラスを削除する方法はありますか?

+0

「ClassLoader」からのアンロードは信頼性がありません。不可能です。 ClassLoaderが到達不能になったが、すべてのクラスがこのローダを参照しているので、このローダによってロードされたすべてのクラスが到達不能になっている必要があることを意味するので、クラスはアンロードできます。しかし、別の* ClassLoaderを使ってクラスを(再)作成することはできます。正式には、正式には同じ名前(同じバイトコード)の別のクラスです。 – Holger

+0

それは答えと思われる...あなたがそれを置くなら、私は受け入れるだろう。 –

答えて

4

ClassLoaderから1つのクラスをアンロードすることはできません。クラスとそのClassLoaderに到達できなくなった場合、すべてのクラスがそのローダーを参照するため、このローダーによってロードされたすべてのクラスが到達不能になっている必要があることを意味するので、クラスはアンロードできます。

しかし、別のClassLoaderを使用してクラスを(再)作成することはできます。正式には、正式には同じ名前(同じバイトコード)の別のクラスです。テストケース内で実行されたコードがヒープ内に参照を残さない場合、ClassLoaderとそのクラスはテスト後に収集される可能性があります。

+0

しかし、2番目のClassLoaderのロードされたクラスが最初のClassLoaderの別のクラスへの参照を持っている場合は、2番目のClassLoaderにすべての参照型も追加する必要がありますか? – Pooya

+1

@Пуя:いくつかの要因によって異なります。 'ClassLoader' C1によって定義されたクラスは、C1が関連するクラスローディング要求をC2に委譲する場合、別の' ClassLoader' C2によって定義された実行時型に解決されるクラスへの参照を持つことがあります。 C2がC1の親ローダーである場合、これは標準的な動作です。しかし、これは、C2のこれらのクラスは変更されず、C2は到達可能なままであり、C1が使用されている間はガベージ・コレクションできないことを意味します。したがって、関連する複数のクラスを一度に変更したい場合は、すべてのクラスを新しいClassLoaderで再定義する必要があります。 – Holger

+0

新しいクラスのインスタンスが、スーパークラスまたはインタフェースタイプが予期される場所で古いインスタンスを置き換えることを意図している場合、その特定のベースタイプまたはインタフェース*はドロップイン置換を可能にするために同じ実行時タイプに解決されなければなりません。 – Holger

0

私は同じ問題を取得し、私はこのようにそれを解決し、テストケースを申請することはできませんことがあります

CtClassあなたのクラスのプライベートな静的変数を確認します。

CtClassが既に構築されているかどうかをチェックするメソッドを作成します。 CtClassがビルドされていない場合は、ビルドするメソッドを呼び出し、それ以外の場合はCtClassを返します。

すべてのテストで新しいメソッドを使用するようにします。

Nテストがある場合、最初のテストだけがCtClassを構築しようとしますが、残りのテストでは静的なCtClass変数が使用されます。

関連する問題