2012-02-28 11 views
5

Przez "zwolniony" mam na myśli to, że nie ma żadnych odniesień do pozostałego modułu ładującego klasy.Kiedy sfinalizowanie jest wywoływane w pojedynczych egzemplarzach po zwolnieniu programu ładującego klasy?

Występuje problem polegający na tym, że często ponownie wdrażana aplikacja Java EE zjada przestrzeń permgen. Analiza pokazuje, że singleton w aplikacji Java EE przekazał odniesienia do obiektów klasy aplikacji ładujących poza aplikacją (z naruszeniem zasad Java EE) i nie usuwa ich po uruchomieniu aplikacji.

Zakładając, że nie ma innych odniesień do singletonu lub obiektu klasy, czy wywołanie singleton's finalize() zostanie wywołane, gdy zwolni się moduł ładujący klasy tej klasy? Chciałbym usunąć tam fałszywe referencje. Czy jestem w haczyku-22, w którym finalizacja nie zostanie wywołana, dopóki sam program ładujący klasy nie będzie mógł zostać zebrany - a zatem nigdy nie zostanie wywołany z powodu fałszywych zewnętrznych odniesień?

Głównym pytaniem jest chyba tutaj:

będzie obiektem klasy być śmieci zgromadzone w tym przypadku, gdy jego classloader nie można jeszcze? Może to być zależne od specyfikacji zachowania modułu ładującego lub może być zależne od implementacji.

Referencje (inny rodzaj! ;-)) byłyby docenione, ale nie są konieczne.

+0

Jeśli zdasz referencje ClassLoaders rozważyć użycie WeakReference (y) i WeakHashMap zamiast silnych (regularny) referencje. – Stefan

Odpowiedz

4

Klasa ze statycznym odwołaniem do niego, będzie uprawniona tylko do zbierania śmieci, jeśli program ładujący klasy kwalifikuje się do GCing i nie ma innych odniesień do niego.

klasy lub interfejsu mogą być rozładowywane tylko wtedy, gdy jego zdefiniowanie ładowarka klasy mogą być odzyskane przez garbage collector.

http://java.sun.com/docs/books/jls/third_edition/html/execution.html#12.7

Ponadto każda klasa ma odniesienie do jego classloader. Tak więc program ładujący klasy nie kwalifikuje się do GCing tak długo, jak istnieją odniesienia do klas załadowanych przez niego lub obiektów tych klas z obiektów nie kolekcjonowalnych.

Finalizator jest uruchamiany jakiś czas po tym, jak obiekt kwalifikuje się do zbierania śmieci i przed faktycznym przeprowadzeniem GC.

Podejście do bezpłatnych referencji przychodzących, które uniemożliwiają GCing, w finalizatorze nie działa. Finalizator nie zostanie wywołany, dopóki istnieją takie odwołania, ponieważ uniemożliwiają one zakwalifikowanie się obiektu do zbierania śmieci.Na przykład nie można przerwać ten łańcuch odniesienia od wewnątrz:

singleton instance <--- singleton class <--- class loader <-- 
<-- any class loaded by that class loader <-- any object of such a class 
<-- object loaded by another classloader referencing such an object or class 
+0

Odwołania nie są pojedyncze (bezpośrednio lub pośrednio), więc pętla odniesienia nie jest problemem. Najważniejszą rzeczą, którą próbuję zrozumieć, jest to, czy klasa może być GC'd, mimo że istnieją odwołania zewnętrzne wyróżniające się na inne klasy od tego wydanego programu ładującego klasy. –

+0

Co masz na myśli mówiąc "zwolniony". Program ładujący klasy kwalifikuje się tylko do GCing, jeśli wszystkie ładowane przez niego klasy również kwalifikują się do GCing, ponieważ każda klasa ma odwołanie do swojego programu ładującego klasy. –

+0

Ok, a ClassLoader ma wektor wszystkich klas, które wczytał ... więc finalizator nie zadziała niezależnie. Dzięki wielkie! –

0

Zachowanie finalizatorów nie jest zmieniane przez program ładujący klasy lub użycie perm gen, chociaż powoduje pogorszenie wydajności. Obiekty nie mogą być gromadzone do czasu uruchomienia finalizatora. Tak więc (upraszczając przy założeniu, że nie współbieżnie i ignorując słabe/miękkie/fantomowe) istnieje bieg GC, który określa, że ​​nie ma żadnych aktywnych odniesień do wykresu obiektu, w tym modułu ładującego klasy. Finalizatory są dodawane do kolejki finalizatora, a następnie wykonywane. Następnie po kolejnym przejściu GC można odzyskać pamięć. Wymaga to pełnej GC, w tym ponad przestrzenią permen, która jest zwykle rzadka i może być wyłączona.

W każdym razie nie używaj (stanowych) singletonów.

+0

Czy obiekt klasy zostanie zbuforowany w tym przypadku, gdy nie można jeszcze załadować tego modułu? Jest to albo zależne od specyfikacji zachowania klasy ładującego, albo może być zależne od implementacji. –

+0

@EdStaub - Klasa NIGDY nie jest zbierana, dopóki nie będzie można pobrać jej klasy. Ponadto program ładujący klasy nigdy nie jest gromadzony, dopóki nie zostaną zebrane wszystkie załadowane klasy. –

+0

Odniesienia statyczne są nadal osiągalne, gdy klasa jest osiągalna. "Co ciekawe," Tomcat usunie statyczne pola. –

Powiązane problemy