Cześć! Cykl życia obiektu - 1Myślę, że nie zdziwisz się zbytnio, jeśli powiedzą ci, że ilość pamięci w twoim komputerze jest ograniczona :) Nawet dysk twardy, który jest wielokrotnie większy niż pamięć RAM, można zapełnić po brzegi ulubionymi grami, programami telewizyjnymi i więcej. Aby temu zapobiec, musisz monitorować aktualny stan pamięci i usuwać niepotrzebne pliki z komputera. Co ma z tym wszystkim wspólnego programowanie w Javie? Bezpośredni! W końcu podczas tworzenia dowolnego obiektu przez maszynę Java przydzielana jest dla niego pamięć. W naprawdę dużym programie tworzone są dziesiątki i setki tysięcy obiektów, z których każdy ma swój własny fragment w pamięci. Ale jak myślisz, jak długo istnieją wszystkie te obiekty? Czy „żyją” cały czas, gdy działa nasz program? Oczywiście że nie. Przy wszystkich zaletach obiektów Javy nie są one nieśmiertelne :) Obiekty mają swój własny cykl życia. Dzisiaj zrobimy sobie małą przerwę od pisania kodu i zastanowimy się nad tym procesem :) Szczególnie, że jest on bardzo ważny dla zrozumienia programu i zarządzania zasobami. Gdzie więc zaczyna się życie obiektu? Jak osoba - od urodzenia, czyli stworzenia.

Cat cat = new Cat(); // Here the lifecycle of our Cat object begins!
Najpierw wirtualna maszyna Java przydziela wymaganą ilość pamięci do utworzenia obiektu. Następnie tworzy link do niego, w naszym przypadku cat, aby móc go śledzić. Następnie wszystkie zmienne są inicjalizowane, wywoływany jest konstruktor i teraz - nasz świeży obiekt żyje już własnym życiem :) Żywotność obiektów jest różna, nie ma tu dokładnych liczb. W każdym razie przez jakiś czas żyje wewnątrz programu i wykonuje swoje funkcje. Mówiąc ściślej, obiekt „żyje” tak długo, jak długo istnieją do niego odniesienia. Gdy tylko zabraknie linków, obiekt „umiera”. Na przykład:

public class Car {
  
   String model;

   public Car(String model) {
       this.model = model;
   }

   public static void main(String[] args) {
       Car lamborghini  = new Car("Lamborghini Diablo");
       lamborghini = null;

   }

}
W metodzie main()obiekt samochodu Lamborghini Diablo przestaje być żywy w drugiej linii. Był tylko jeden link do niego, a teraz ten link został przypisany null. Ponieważ w Lamborghini Diablo nie ma żadnych linków, staje się „śmieciami”. Link nie wymaga resetowania:

public class Car {

   String model;

   public Car(String model) {
       this.model = model;
   }

   public static void main(String[] args) {
       Car lamborghini  = new Car("Lamborghini Diablo");

       Car lamborghiniGallardo = new Car("Lamborghini Gallardo");
       lamborghini = lamborghiniGallardo;
   }

}
Tutaj stworzyliśmy drugi obiekt, po czym wzięliśmy referencję lamborghinii przypisaliśmy do niego ten nowy obiekt. Lamborghini GallardoIstnieją teraz dwa odwołania do obiektu , ale Lamborghini Diablożadne do obiektu. Dlatego obiekt Diablostaje się śmieciem. I w tym momencie do gry wchodzi wbudowany w Javę mechanizm zwany Garbage Collectorem, czyli Garbage Collectorem, GC.
Cykl życia obiektu - 2
Garbage collector to wewnętrzny mechanizm Javy, który odpowiada za zwalnianie pamięci, czyli usuwanie z niej zbędnych obiektów. Nie na próżno wybraliśmy zdjęcie z robotem odkurzającym do jego wizerunku. W końcu moduł wyrzucania elementów bezużytecznych działa w podobny sposób: w tle „podróżuje” przez twój program, zbiera śmieci, a jednocześnie praktycznie nie wchodzisz z nim w interakcję. Jego zadaniem jest usuwanie obiektów, które nie są już używane w programie. W ten sposób zwalnia pamięć w komputerze dla innych obiektów. Pamiętasz, jak na początku wykładu powiedzieliśmy, że w zwykłym życiu trzeba monitorować stan swojego komputera i usuwać stare pliki? Cóż, w przypadku obiektów Java, Garbage Collector robi to za Ciebie. Garbage Collector uruchamia się wiele razy podczas działania twojego programu: nie musisz go specjalnie wywoływać i wydawać poleceń, chociaż jest to technicznie możliwe. Później porozmawiamy o tym i bardziej szczegółowo przeanalizujemy proces jego pracy. W momencie, gdy Garbage Collector dotarł do obiektu, tuż przed jego zniszczeniem, na obiekcie wywoływana jest specjalna metoda -finalize(). Można go użyć do zwolnienia dodatkowych zasobów, z których obiekt korzystał. Metoda finalize()należy do Object. To znaczy, wraz z equals(), hashCode()i toString(), z którymi już wcześniej się spotkałeś, ma go każdy przedmiot. Różni się ona od innych metod tym, że jest… jakby to powiedzieć… bardzo kapryśna. Mianowicie przed zniszczeniem obiektu nie zawsze jest to tzw. Programowanie to rzecz precyzyjna. Programista każe komputerowi coś zrobić, a komputer to robi. Przypuszczam, że jesteś już przyzwyczajony do takiego zachowania i na początku może ci być trudno zaakceptować pomysł: „Zanim obiekty zostaną zniszczone, metoda klasowa finalize()nazywa się Object. Albo nie dzwonił. Jeśli nam się poszczęści!” Jednak to prawda. Maszyna Java sama określa, czy wywołać metodęfinalize()indywidualnie, czy nie. Na przykład spróbujmy uruchomić następujący kod na potrzeby eksperymentu:

public class Cat {

   private String name;

   public Cat(String name) {
       this.name = name;
   }

   public Cat() {
   }

   public static void main(String[] args) throws Throwable {
       for (int i = 0 ; i < 1000000; i++) {
           Cat cat = new Cat();
           cat = null; // This is when the first object becomes available to the garbage collector
       }
   }

   @Override
   protected void finalize() throws Throwable {
       System.out.println("Cat object destroyed!");
   }
}
Tworzymy obiekt Catiw kolejnym wierszu kodu unieważniamy jedyną referencję do niego. I tak - milion razy. Wyraźnie zastąpiliśmy tę metodę finalize()i powinna ona wyświetlać ciąg znaków na konsoli milion razy, za każdym razem przed zniszczeniem obiektu Cat. Ale nie! Dla ścisłości, na moim komputerze zadziałało to tylko 37346 razy! Oznacza to, że tylko w 1 przypadku na 27 maszyna Java, którą zainstalowałem, podjęła decyzję o wywołaniu metody finalize()- w innych przypadkach wyrzucanie elementów bezużytecznych odbywało się bez niej. Spróbuj uruchomić ten kod dla siebie: najprawdopodobniej wynik będzie inny. Jak widać finalize()trudno nazwać solidnym partnerem :) Dlatego mała rada na przyszłość: nie polegaj na metodziefinalize()w przypadku uwolnienia niektórych krytycznych zasobów. Może JVM to wywoła, a może nie. Kto wie? Jeśli Twój obiekt podczas swojego życia zajmował jakieś zasoby, które są bardzo ważne dla wydajności, na przykład utrzymywał otwarte połączenie z bazą danych, lepiej stworzyć specjalną metodę w swojej klasie, aby je zwolnić i wywołać ją jawnie, gdy obiekt nie będzie już potrzebny. Dzięki temu będziesz mieć pewność, że wydajność Twojego programu nie ucierpi. Na samym początku powiedzieliśmy, że praca z pamięcią i wyrzucaniem elementów bezużytecznych jest bardzo ważna i to prawda. Niewłaściwe obchodzenie się z zasobami i niezrozumienie procesu składania niepotrzebnych obiektów może prowadzić do wycieków pamięci. To jeden z najbardziej znanych błędów w programowaniu. Kod napisany niepoprawnie przez programistę może doprowadzić do że dla nowo tworzonych obiektów każdorazowo zostanie przydzielona nowa pamięć, podczas gdy stare, niepotrzebne obiekty nie będą dostępne do usunięcia przez Garbage Collector. Ponieważ podaliśmy analogię z robotem odkurzającym, wyobraź sobie, co się stanie, jeśli przed uruchomieniem robota rozrzucisz skarpetki po całym domu, stłuczesz szklany wazon i zostawisz rozmontowany konstruktor Lego na podłodze. Robot oczywiście będzie próbował coś zrobić, ale w pewnym momencie utknie.
Cykl życia obiektu - 3
Aby działał prawidłowo, należy utrzymywać podłogę w dobrym stanie i usuwać stamtąd wszystko, czego odkurzacz nie jest w stanie udźwignąć. Ta sama zasada dotyczy śmieciarza. Jeśli w programie pozostało wiele przedmiotów, których nie może zebrać (jak skarpetka lub klocki Lego do robota odkurzającego), w pewnym momencie pamięć się wyczerpie. I nie tylko program, który napisałeś, może się zawiesić, ale także wszystkie inne programy uruchomione w tym momencie na komputerze. Dla nich też może być za mało pamięci.

Nie trzeba go zapamiętywać: wystarczy zrozumieć zasadę działania.