Przeglądałem stare książki i znalazłem egzemplarz „Practical Java” Petera Haggera. W sekcji dotyczącej wydajności znajduje się zalecenie, aby ustawić odniesienia do obiektów, null
gdy nie są już potrzebne.
Czy w Javie ustawianie odwołań do obiektów null
poprawia wydajność lub efektywność usuwania pamięci? Jeśli tak, w jakich przypadkach jest to problem? Klasy kontenerów? Kompozycja obiektu? Anonimowe klasy wewnętrzne?
Widzę to dość często w kodzie. Czy jest to przestarzała rada dotycząca programowania, czy nadal jest przydatna?
Odpowiedzi:
To zależy trochę od tego, kiedy myślałeś o anulowaniu odniesienia.
Jeśli masz łańcuch obiektów A-> B-> C, to gdy A jest nieosiągalny, A, B i C będą wszystkie kwalifikować się do czyszczenia pamięci (zakładając, że nic innego nie odwołuje się do B lub C). Nie ma potrzeby i nigdy nie było potrzeby, aby na przykład jawnie ustawić odwołania A-> B lub B-> C na null.
Poza tym przez większość czasu problem tak naprawdę nie występuje, ponieważ w rzeczywistości masz do czynienia z obiektami w kolekcjach. Generalnie powinieneś zawsze myśleć o usunięciu obiektów z list, map itp. Poprzez wywołanie odpowiedniej metody remove ().
Przypadek, w którym kiedyś istniały porady dotyczące ustawiania odwołań na wartość null, dotyczył szczególnie długiego zakresu, w którym obiekt intensywnie wykorzystujący pamięć przestał być używany w części zakresu . Na przykład:
Uzasadnieniem tutaj było to, że ponieważ obj nadal zakres, a następnie bez wyraźnej Nulling odniesienia, to nie staje się śmieci kolekcjonerów aż po doSomethingElse () zakończy metod. I to jest rada, której prawdopodobnie już nie ma w nowoczesnych maszynach JVM : okazuje się, że kompilator JIT może ustalić, w którym momencie dane odwołanie do obiektu lokalnego nie jest już używane.
źródło
Nie, to nie jest przestarzała rada. Wiszące odwołania nadal stanowią problem, zwłaszcza jeśli, powiedzmy, implementujesz kontener z rozszerzalną tablicą (
ArrayList
lub podobny) przy użyciu wstępnie przydzielonej tablicy. Elementy wykraczające poza „logiczny” rozmiar listy powinny zostać usunięte, w przeciwnym razie nie zostaną zwolnione.Zobacz Effective Java 2nd ed, Item 6: Eliminate Obsolete Object References.
źródło
Pola instancji, elementy tablic
Jeśli istnieje odwołanie do obiektu, nie można go wyrzucić. Szczególnie jeśli ten obiekt (i cały wykres za nim) jest duży, istnieje tylko jedno odniesienie, które zatrzymuje czyszczenie pamięci i to odniesienie nie jest już potrzebne, jest to niefortunna sytuacja.
Przypadki patologiczne to obiekt, który zachowuje nieistotną instancję w całym drzewie XML DOM, które zostało użyte do jej skonfigurowania, komponent MBean, który nie został wyrejestrowany, lub pojedyncze odwołanie do obiektu z niezainstalowanej aplikacji internetowej, które zapobiega wyładowaniu całego modułu ładującego klasy .
Więc jeśli nie jesteś pewien, że obiekt, który przechowuje samo odniesienie, i tak zostanie usunięty jako śmieci (lub nawet wtedy), powinieneś wyzerować wszystko, czego już nie potrzebujesz.
Zmienne z zakresem:
Jeśli rozważasz ustawienie zmiennej lokalnej na wartość null przed końcem jej zakresu, aby mogła zostać odzyskana przez moduł wyrzucania elementów bezużytecznych i oznaczyć ją jako „bezużyteczną od teraz”, powinieneś zamiast tego rozważyć umieszczenie jej w bardziej ograniczonym zakresie .
staje się
Długie, płaskie zakresy są również ogólnie złe dla czytelności kodu. Nie jest też niczym niezwykłym wprowadzenie prywatnych metod rozbijania rzeczy tylko w tym celu.
źródło
Może to być przydatne w środowiskach o ograniczonej pamięci (np. Telefony komórkowe). Ustawiając wartość null, obiekt objetc nie musi czekać, aby zmienna wyszła poza zakres, aby została przypisana do elementu gc.
Jednak w codziennym programowaniu nie powinno to być regułą, z wyjątkiem szczególnych przypadków, takich jak ten, który przytoczył Chris Jester-Young.
źródło
Po pierwsze, nie oznacza to niczego, do czego ustawiasz obiekt
null
. Wyjaśnię to poniżej:W powyższym segmencie kodu tworzymy nazwę zmiennej odniesienia
list1
doArrayList
obiektu, która jest przechowywana w pamięci. Tak więclist1
odnosi się do tego obiektu i jest to tylko zmienna. W drugim wierszu kodu kopiujemy odwołanielist1
dolist2
. A teraz wracając do twojego pytania, jeśli to zrobię:oznacza
list1
to, że nie odnosi się już do żadnego obiektu, który jest przechowywany w pamięci, więclist2
również nie będzie miał nic do odniesienia. Więc jeśli sprawdzisz rozmiarlist2
:Tak więc pojawia się koncepcja garbage collector, która mówi: „Nie musisz się martwić o uwolnienie pamięci przechowywanej przez obiekt, zrobię to, gdy stwierdzę, że nie będzie już używany w programie, a JVM będzie mną zarządzać”.
Mam nadzieję, że wyjaśni to koncepcję.
źródło
Jednym z powodów takiego działania jest wyeliminowanie przestarzałych odniesień do obiektów. Możesz przeczytać tekst tutaj.
źródło