2012-01-09 13 views
5

Do projektu potrzebujemy sposobu uruchamiania skryptów użytkownika, które mogą być dostarczane z dołączonymi plikami JAR z dodatkowymi klasami.Jak mogę przeprowadzić test jednostkowy GC?

Jakie są moje opcje, gdy chcę napisać kilka testów, aby upewnić się, że normalny skrypt nie pozostawia nic wiszącego w tyle?

Muszę wiedzieć: czy wszystkie klasy z załączonych JAR-ów są "rozładowane"?

Uwaga: Nie szukam w 100% super wodoszczelnego rozwiązania, które działa we wszystkich wersjach Javy od 1.0 do 7. Teraz muszę po prostu być lepszy niż "Nie mam pojęcia".

+0

Dlaczego mieliby być rozładowane? Czy masz na myśli, że ich instancje będą GCed, tj. Kod i biblioteki skryptów użytkownika nie mają przecieków pamięci? Czy ładujesz je za pomocą nowego programu ładującego klasy? –

+0

Tak. To, co chciałbym, to sposób, by zapytać GC "czy mógłbyś teraz GC na tym przykładzie?" A może "powiedz mi, ile odniesień istnieje dla instancji' foo' "Jak robią to profilerzy? –

Odpowiedz

3

Najprawdopodobniej najlepszą opcją jest zapewnienie załadowania załadowanych słoików przez określony program ładujący klasy, a następnie odrzucenie tego programu ładującego klasy (po odrzuceniu wszystkich obiektów).

Jeśli chodzi o testowanie rozładunku, jeśli wybierzesz tę opcję, musisz rozszerzyć swoją strukturę testową i niestandardowe programy ładujące klasy, aby flaga "Utwórz moduł ładujący klasy na żądanie". Następnie wczytujesz klasę z włączoną flagą, odrzucisz program ładujący klasy i spróbujesz ponownie załadować klasę z wyłączoną flagą. Jeśli klasa jest naprawdę nieosiągalna, druga próba powinna rzucić wyjątek klasy nieznajdujący. Następnie przechodzisz testy jednostkowe, aby przejść, jeśli należą do wyjątku, i nie powiedzie się, jeśli uda im się trafić linię po drugiej próbie obciążenia.

Jeśli jesteś skłonny używać więcej niż czystych narzędzi Java, może być rozważany kontener OSGi. Większość wdrożonych implementacji kontenerów OSGi wyraźnie testuje rozładunek klasy.

+0

+1 dla drugiej opcji.Aby mieć 100% pewności (co nie jest wymagane), prawdopodobnie trzeba uruchomić moduł ładujący klasy z menedżerem zabezpieczeń (aby upewnić się, że skrypty nie utworzyły wątków itp.). –

+0

@Sean Reilly, Dzięki. Pozostałe opcje stały się szumami, więc przesunąłem wiadomość bliżej szczytu. –

+0

Chodzi o to, że Aaron już robi to, co opisujesz w swoim pierwszym akapicie, ale ponieważ nie możesz jawnie odrzucić obiektów Java, chce on, aby sprawdzić, czy rzeczywiście dzieje się to w sposób dorozumiany, czy też istnieje przeciek. –

3

Nie próbowałbym tego testować. Zamiast tego uruchomiłbym maszynę JVM z opcją -XX: -TraceClassUnloading i sprawdzam, czy dane klasy pojawiają się w wynikach śledzenia.

1

Wszystko zależy od sposobu uruchomienia skryptów. Czy mają dostęp do klas reszty aplikacji?

Typowym sposobem wycieku pamięci w Javie jest posiadanie statycznego odwołania. Odniesienie statyczne jest statyczne tylko w klasie Classoader klasy, która go zawiera. Tak więc, jeśli wczytasz swoje skrypty użytkownika za pomocą ClassLoader, którym zarządzasz (i mimo to powinieneś to zrobić), odniesienia (statyczne lub nie) w środku będą podlegały GC, gdy tylko będzie to Twój program ładujący klasy.

Jedynym sposobem, w jaki mogą to obejść, jest dodanie odniesienia do jednego z ich obiektów do jednego z nich. Musisz więc bardzo uważać na interfejs API, który eksponujesz. Innym sposobem jest stworzenie statycznego odwołania do swojej klasy w klasie innej klasy ClassLoader.

Nie widzę sposobu, aby w pełni zautomatyzować testowanie tego. Ale przypuszczam, że można było prześledzić rozładunek klasy przy pomocy przyzwoitego profilera.

2

Wygląda na to, że chcesz sprawdzić, czy skrypty węża nie mają classloader leak.

Aby to zrobić, chciałbym stworzyć WeakReference do ClassLoader używany do załadowania tego JAR, a następnie uruchomić skrypt, a następnie zadzwonić System.gc() a potem assertNull(reference.get())

+0

Alternatywą może być utworzenie instancji obiektu URLClassLoader na JAR i użycie go do załadowania klas. Trash it (ustawiona na null) po zakończeniu. – aishwarya

+1

@aishwarya: to wcale nie jest "alternatywa". Nie można "wyrzucać" obiektów java. Ustawienie odwołania do wartości null pozwala tylko na zbieranie obiektu, jeśli nie ma innych odniesień. Opisuję to, jak przetestować, czy obiekt * był * faktycznie zbędny. Classloadery są bardzo trudne do pozbycia się, ponieważ jedno odniesienie do jednego obiektu dowolnej z załadowanych klas ukrytych w zbiorze gdzieś jest wystarczające, aby uniemożliwić ładowanie klas i wszystkie załadowane przez niego klasy z śmieci. –

Powiązane problemy