Czy pola statyczne są otwarte do czyszczenia pamięci?


96

Biorąc pod uwagę hipotetyczną klasę narzędziową, która jest używana tylko w konfiguracji programu:

class MyUtils {
   private static MyObject myObject = new MyObject();
   /*package*/static boolean doStuff(Params... params) {
       // do stuff with myObject and params...
   }
}

czy myObject będzie zbierany jako śmieci, gdy nie będzie już używany, czy też pozostanie przez całe życie programu?

Odpowiedzi:


113

Nie można wybrać zmiennych statycznych do czyszczenia pamięci podczas ładowania klasy. Można je zebrać, gdy odpowiedni program ładujący klasy (który był odpowiedzialny za załadowanie tej klasy) sam jest zbierany do śmieci.

Zapoznaj się z sekcją JLS 12.7 Rozładowywanie klas i interfejsów

Klasa lub interfejs mogą zostać wyładowane wtedy i tylko wtedy, gdy ich definiujący program ładujący klasy może zostać odzyskany przez moduł odśmiecania pamięci [...] Klasy i interfejsy załadowane przez moduł ładujący nie mogą zostać usunięte.


@bruno, Czy to oznacza, że ​​program ładujący klasy zawiera odniesienie do każdej ładowanej klasy, nawet jeśli ładowana klasa nie ma statycznych elementów członkowskich?
Pacerier,

@brunoconde, nie sądzę, że to prawda. Który dokładnie akapit to stwierdza? (Kontynuuj dyskusję na stackoverflow.com/questions/405364/ ... )
Pacerier,

Kiedy program ładujący klasy kwalifikowałby się do czyszczenia pamięci. ?
Rohit Bandil

@RohitBandil - gdy jest nieosiągalny.
Stephen C

55

Do zmiennych statycznych odwołują się obiekty Class, do których odwołują się ClassLoaders - więc chyba że ClassLoader w jakiś sposób upuści Class (jeśli jest to w ogóle możliwe) lub sam ClassLoader będzie kwalifikował się do zbierania (bardziej prawdopodobne - pomyśl o wyładowaniu aplikacji internetowych) zmiennych statycznych (lub raczej obiekty, do których się odnoszą), nie zostaną zebrane.


1
Czy do Classobiektów, które nie zawierają zmiennych statycznych, odwołuje się program ładujący klasy?
Pacerier

14

Jeśli chcesz, aby tymczasowy obiekt był używany do statycznej inicjalizacji, a następnie został usunięty, możesz użyć statycznego bloku inicjalizatora, np.

class MyUtils {
   static
   {
      MyObject myObject = new MyObject();
      doStuff(myObject, params);
   }

   static boolean doStuff(MyObject myObject, Params... params) {
       // do stuff with myObject and params...
   }
}

ponieważ statyczny blok inicjalizatora jest specjalnym rodzajem statycznej metody, myObject jest zmienną lokalną i może zostać usunięty po zakończeniu wykonywania bloku.


13

myObject jest odniesieniem, a nie obiektem . Obiekt jest automatycznie usuwany jako śmieci, gdy żadne odniesienie do niego nie wskazuje, ponieważ jest nieosiągalny.

Zatem także obiekt znajdujący się za statycznym odwołaniem „myObject” może zostać usunięty, jeśli wyłuskujemy go za pomocą

myObject = null;

i nie ma innych odniesień do tego obiektu.

Jednak statyczne odniesienia i zmienne pozostają przez cały okres istnienia programu.


Witamy w StackOverflow! Ustawienie obiektu nullna koniec static blockjest realną opcją. Jednak w moim przypadku żywotność obiektu musiała być dłuższa niż statyczny blok. Koniec użyteczności obiektu nie był zbyt konkretny; dlatego pytam o wykorzystanie kolektora śmieci.
Michael Deardeuff,

7

Myślę, że to odpowiada na twoje pytanie - w zasadzie nie, chyba że klasa pochodzi ze specjalnego modułu ładującego klasy, który rozładowuje klasę.


0

Kluczem jest tutaj Garbage Collection instancji klas, czyli obiektów. Instancja ClassLoader jest w istocie obiektem. Więc jeśli obiekt Classloader nie jest wyrzucany do śmieci, wszelkie odniesienia do nich przechowywane w stercie (tj. Statyczne rzeczy) prawie nigdy nie będą zbierane jako śmieci. Wyjątkiem jest pula ciągów.

Więc zanim nagle zdecydujesz się to zrobić private static MyGiantClass myGiantObject = new MyGiantClass() Pomyśl dwa razy, tak jak nauczyłem się na własnej skórze.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.