2013-06-26 7 views
5

Używam Javassist do stworzenia klasy. A w pakiecie testowym, gdy drugi test próbuje utworzyć tę samą klasę, nie powiedzie się na pool.makeClass(...), ponieważ klasa jest zamrożona (tj. Już utworzona przez toClass(). usunąć klasę jakoś - może wyładować z classloader. - ale jak czytam in JLS operacja wyładowania nie jest niezawodnyJavassist: ponowne utworzenie klasy - usunąć pierwsze lub odszraniać() i modyfikować?

Więc być może rozwiązaniem jest sprawdzić w klasie tworzenia kodu, czy istnieje, a jeśli tak, to defrost() usuń wszystkich członków itp. i ponownie je stwórz.

Jakieś inne pomysły?

Czy jest jakiś niezawodny sposób na usunięcie klasy przez Javassist?

+0

Rozładowanie z 'ClassLoadera' nie jest niewiarygodne - niemożliwe. Klasa może zostać rozładowana, jeśli * i * jej 'ClassLoader' stanie się nieosiągalna, ale ponieważ każda klasa odwołuje się do jej programu ładującego, co oznacza, że ​​* wszystkie * klasy ładowane przez ten program ładujący również musiały stać się nieosiągalne. Ale możesz (re) stworzyć klasę używając * innego * 'ClassLoader'. Cóż, formalnie jest to inna klasa o tej samej nazwie (i może ten sam kod bajtowy). – Holger

+0

To wydaje się być odpowiedzią ... jeśli to ułożysz, zaakceptuję. –

Odpowiedz

4

Nie można zwolnić pojedynczej klasy z ClassLoader. Klasa może zostać rozładowana, jeśli jej i jej ClassLoader stanie się nieosiągalna, ale ponieważ każda klasa odwołuje się do jej programu ładującego, co oznacza, że ​​wszystkie klasy załadowane przez tę ładowarkę również musiały stać się nieosiągalne.

Ale możesz (re) stworzyć klasę przy użyciu innego ClassLoader. Cóż, formalnie jest to inna klasa o tej samej nazwie (i może ten sam kod bajtowy). Jeśli kod wykonany w teście nie pozostawia żadnych odniesień w stercie, ClassLoader i jego klasy mogą zostać zebrane po teście.

+0

Ok, ale jeśli załadowana klasa w drugiej klasie ClassLoader ma odniesienia do innych klas pierwszej klasy Classoader, czy powinniśmy również dodać wszystkie typy referencji do drugiej klasy ClassLoader? – Pooya

+1

@ Пуя: To zależy od kilku czynników. Klasa zdefiniowana przez 'ClassLoader' C1 może mieć odwołania do klas, które są rozwiązywane dla typów środowiska wykonawczego zdefiniowanych przez inną klasę" ClassLoader "C2, jeśli C1 deleguje powiązane żądania ładowania klas do C2. Jest to standardowe zachowanie, jeśli C2 jest * rodzicielskim * ładownikiem C1. Oznacza to jednak, że te klasy w C2 pozostają niezmienione, a C2 pozostaje osiągalne i nie można ich pozbyć się podczas używania C1. Więc jeśli chcesz zmodyfikować wiele powiązanych klas jednocześnie, wszystkie z nich muszą zostać przedefiniowane w nowym 'ClassLoader'. – Holger

+0

Jeśli instancje nowej klasy mają zastąpić stare w miejscach, w których oczekiwana jest super klasa lub typ interfejsu, ten konkretny typ podstawowy lub interfejs * musi * zostać rozwiązany dla tego samego typu środowiska wykonawczego, aby umożliwić zastąpienie wtyczki. – Holger

0

mam ten sam problem i rozwiązać go w ten sposób, może być nie może mieć zastosowania w Twoim przypadku testu:

Bądź CtClass prywatny statyczna zmienna swojej klasie.

Utwórz metodę, która sprawdza, czy obiekt CtClass jest już zbudowany. Jeśli CtClass nie jest zbudowany, wywołaj metodę, która go buduje, w przeciwnym razie zwróć tę klasę CtClass.

Spraw, aby wszystkie testy były wykonywane przy użyciu nowej metody.

Tak więc, jeśli masz N Test, tylko pierwszy spróbuje zbudować CtClass, reszta z nich będzie miała statyczną zmienną CtClass.

Powiązane problemy