2011-11-19 8 views
10

Mam klasę Java, która używa złożonych pól statycznych, które wymagają specjalnych operacji jako close(), dzięki czemu są bezpiecznie czyszczone przez GC.Rozładuj pola statyczne

Do inicjalizacji pól statycznych używam bloku static. Ale nie wiem teraz, jak bezpiecznie rozładować pole statyczne, aby móc wywołać metodę close() zanim pole zostanie oczyszczone przez GC.

Czy istnieje sposób na wyładowanie pola statycznego, podobnie do bloku inicjalizacji statycznej?

+1

Czy rozważałeś użycie funkcji finalize()? –

+2

Mam. Ale z tego, co wiem, sfinalizowanie działa na obiektach klasy, a nie na polach statycznych z tej klasy. Więc sfinalizowanie nie jest dla mnie opcją. –

+0

Może za pomocą statycznego pola zawierającego liczbę aktywnych odwołań do obiektów tej klasy (inkrementowanego w konstruktorze, zmniejszonego w finalize()) ORAZ wywołującego close() lub jakichkolwiek metod czyszczenia, które masz na "złożonej" statyce po sfinalizowaniu () napotyka liczbę ref zera po zmniejszeniu - nie próbowałem tego. –

Odpowiedz

8

Nie ma sposobu, aby zrobić to, o co prosisz, ponieważ blok statyczny zostaje zainicjowany, gdy klasa jest załadowana i sfinalizowana() działa tylko na obiektach.

Zastanów się nad zastąpieniem zmiennych statycznych i złożonej operacji za pomocą klasy Singleton i jej instancji.

W ten sposób można użyć metody finalize() w celu wykonania czynności close().

-2

nr

Klasy statyczne są ładowane przy starcie, kiedy pierwszy raz go użyć, i rozładowywane tylko wtedy, gdy program wychodzi (AFAIK).

Dzięki temu można stworzyć statyczną metodę close w samej klasie, która czyści statyczne elementy i wywołuje ją po zamknięciu.

+1

A jeśli jest to aplikacja internetowa, skąd wiadomo, kiedy kończę pracę? –

+0

nie, można rozładować klasy, gdy program wciąż żyje. – jtahlborn

1

Możesz skonfigurować shutdown hook, aby to osiągnąć, ale możesz nie być w stanie wykonać wszystkich czynności. Być może zabrakło Ci pamięci lub proces mógł zostać zabity bez umożliwienia oczyszczenia, itp.

Lepiej jest upewnić się, czy konsystencja danych nie zależy od tego kodu i/lub przenieść to kod, który czyści się regularnie w trakcie trwania aplikacji.

+0

'ServletContextListener' jest lepszym rozwiązaniem niż hak zamykający dla aplikacji internetowych. Zobacz http://stackoverflow.com/questions/6950396/contextdestroyed-vs-addshutdownhook –

+0

@Kublai, w kontekście kontenera serwletu Zgadzam się, OP nie wspomina kontekstu internetowej aplikacji w dowolnym miejscu w jej pytaniu jednak. – rsp

+0

Wspomniała o tym w swoim komentarzu do odpowiedzi Zom-B - zgodziła się, że pytanie powinno o tym wspomnieć. –

2

W aplikacji internetowej można użyć numeru ServletContextListener.

+1

+1 To jest droga, IMO. ['contextDestroyed()'] (http://download.oracle.com/javaee/6/api/javax/servlet/ServletContextListener.html#contextDestroyed (javax.servlet.ServletContextEvent)) jest wywoływany dokładnie raz podczas cofania wdrożenia. Jeśli to konieczne, ['contextInitialized()'] (http://download.oracle.com/javaee/6/api/javax/servlet/ServletContextListener.html#contextInitialized (javax.servlet.ServletContextEvent)) można również użyć do jawnego zainicjowania tych pól statycznych podczas wdrażania, zamiast czekać na załadowanie ich konkretnej klasy. –

3
private static Uninit cleanup = new Uninit(); 
.... 
private static class Uninit { 
    public Uninit() {} 

    public void finalize() { 

        //whatever you need done 

    } 
} 
+0

To wydaje się być miłym trikiem, jeśli chcesz uniknąć implementacji singletonu. Możesz nawet użyć prywatnej anonimowej klasy. Czy są na tym jakieś wady? – Griddo

+0

To będzie działać tylko wtedy, gdy finalizatorzy zostaną wezwani. –