Oto nieco inny przykład, jeden z końcowymi polami typu odwołania zamiast końcowymi zmiennymi lokalnymi typu wartości:
public class MyClass {
public final MyOtherObject obj;
}
Za każdym razem, gdy tworzysz instancję MyClass, będziesz tworzyć wychodzące odwołanie do instancji MyOtherObject, a GC będzie musiał podążać za tym linkiem, aby wyszukać obiekty na żywo.
JVM korzysta z algorytmu GC typu mark-sweep, który musi sprawdzać wszystkie odniesienia na żywo w lokalizacjach „root” GC (podobnie jak wszystkie obiekty w bieżącym stosie wywołań). Każdy żywy obiekt jest „oznaczany” jako żywy, a każdy obiekt, do którego odnosi się żywy obiekt, jest również oznaczany jako żywy.
Po zakończeniu fazy oznaczania GC przeszukuje stertę, zwalniając pamięć dla wszystkich nieoznakowanych obiektów (i zwalniając pamięć dla pozostałych aktywnych obiektów).
Ponadto ważne jest, aby zdać sobie sprawę, że pamięć sterty Java jest podzielona na „młode pokolenie” i „starsze pokolenie”. Wszystkie obiekty są początkowo przydzielane do młodego pokolenia (czasami określane jako „żłobek”). Ponieważ większość obiektów jest krótkotrwała, GC jest bardziej agresywna w kwestii uwalniania ostatnich śmieci od młodego pokolenia. Jeśli obiekt przetrwa cykl kolekcji młodego pokolenia, zostaje przeniesiony do starego pokolenia (czasami nazywanego „pokoleniem najemnym”), które jest przetwarzane rzadziej.
Tak więc, na samą myśl, powiem „nie, 'ostateczny' modyfikator nie pomaga GC zmniejszyć obciążenia pracą”.
Moim zdaniem najlepszą strategią optymalizacji zarządzania pamięcią w Javie jest jak najszybsze wyeliminowanie fałszywych odwołań. Możesz to zrobić, przypisując „null” odwołaniu do obiektu, gdy tylko skończysz go używać.
Lub, jeszcze lepiej, zminimalizuj rozmiar każdego zakresu deklaracji. Na przykład, jeśli zadeklarujesz obiekt na początku metody 1000-liniowej i jeśli obiekt pozostanie żywy aż do zamknięcia zakresu tej metody (ostatni zamykający nawias klamrowy), wówczas obiekt może pozostać żywy znacznie dłużej niż w rzeczywistości niezbędny.
Jeśli użyjesz małych metod, z zaledwie kilkunastoma liniami kodu, to zadeklarowane w tej metodzie obiekty szybciej wyjdą poza zakres, a GC będzie mógł wykonać większość swojej pracy w ramach młoda generacjA. Nie chcesz, aby obiekty były przenoszone do starszej generacji, chyba że jest to absolutnie konieczne.