CodeGym /Blog Java /Random-PL /Cykl życia obiektu
Autor
John Selawsky
Senior Java Developer and Tutor at LearningTree

Cykl życia obiektu

Opublikowano w grupie Random-PL
Cześć! Myślę, że nie byłbyś bardzo zaskoczony, gdybym ci powiedział, że twój komputer ma ograniczoną ilość pamięci :)
Cykl życia obiektu - 1
Nawet twój dysk twardy (który jest wielokrotnie większy niż pamięć RAM) może być wypełniony twoimi ulubionymi grami, programami telewizyjnymi i innymi rzeczami. Aby temu zapobiec, należy monitorować aktualny stan pamięci komputera i usuwać niepotrzebne pliki. Jak to wszystko ma się do programowania w Javie? Całkiem bezpośrednio! W końcu utworzenie dowolnego obiektu powoduje, że maszyna Java przydziela mu pamięć . Duży program działający w świecie rzeczywistym tworzy dziesiątki lub setki tysięcy obiektów, a dla każdego z nich przydzielany jest fragment pamięci. Ale jak myślisz, ile takich obiektów istnieje? Czy „żyją” przez cały czas działania naszego programu? Oczywiście nie. Mimo wszystkich swoich zalet, obiekty Java nie są nieśmiertelne :) Obiekty mają swój własny cykl życia. Dzisiaj zrobimy sobie małą przerwę od pisania kodu i przyjrzymy się temu procesowi :) Jest to również bardzo ważne dla zrozumienia działania programu i zarządzania zasobami. Gdzie więc zaczyna się życie obiektu? Jak człowiek, od urodzenia, czyli od momentu stworzenia.

Cat cat = new Cat();// Our Cat object's lifecycle begins now!
Najpierw wirtualna maszyna Java przydziela pamięć niezbędną do utworzenia obiektu. Następnie tworzy odniesienie do niego (w naszym przypadku cat), aby umożliwić jego śledzenie. Następnie wszystkie zmienne są inicjalizowane, wywoływany jest konstruktor, a nasz świeży obiekt żyje własnym życiem :) Czasy życia obiektów są różne. Nie ma tutaj dokładnych liczb. W każdym razie obiekt żyje w programie i spełnia swoje funkcje przez pewien okres czasu. Mówiąc ściślej, obiekt jest „żywy”, o ile istnieją do niego odniesienia. Gdy tylko nie ma odniesień, 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 main()metodzie obiekt samochodowy „Lamborghini Diablo” przestaje być żywy w drugiej linii. Było tylko jedno odwołanie do niego, a odwołanie zostało ustawione na wartość null. Ponieważ nie ma żadnych pozostałych odniesień do Diablo, staje się „śmieciami”. Odniesienie nie musi być ustawione na zero, aby tak się stało:

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 i przypisaliśmy go do referencji lamborghini. Teraz dwa odniesienia wskazują na Lamborghini Gallardoobiekt, ale Lamborghini Diabloobiekt nie ma żadnego. Oznacza to, że Diabloobiekt staje się śmieciem. W tym momencie włącza się wbudowany moduł wyrzucania elementów bezużytecznych (GC) w Javie.
Cykl życia obiektu - 2
Garbage collector to wewnętrzny mechanizm Javy odpowiedzialny za zwalnianie pamięci, czyli usuwanie zbędnych obiektów z pamięci. Jest powód, dla którego zdecydowaliśmy się przedstawić go za pomocą robota odkurzającego. Garbage collector działa mniej więcej w ten sam sposób: „porusza się” po twoim programie w tle, zbierając śmieci. Praktycznie nie musisz z nim wchodzić w interakcje. Jego zadaniem jest usuwanie obiektów, które nie są już używane w programie. W ten sposób zwalnia pamięć dla innych obiektów. Czy pamiętasz, że na początku lekcji powiedzieliśmy, że w prawdziwym życiu musisz monitorować stan swojego komputera i usuwać stare pliki? Jeśli mówimy o obiektach Java, moduł wyrzucania elementów bezużytecznych robi to za Ciebie. Garbage collector jest uruchamiany wiele razy podczas działania twojego programu: nie musisz go jawnie wywoływać i wydawać mu poleceń (chociaż jest to technicznie możliwe). Później porozmawiamy więcej o wyrzucaniu elementów bezużytecznych i bardziej szczegółowo przeanalizujemy, jak to działa. finalize()Gdy moduł wyrzucania elementów bezużytecznych dotrze do obiektu — tuż przed jego zniszczeniem — wywoływana jest specjalna metoda obiektu . Metodę tę można wywołać w celu zwolnienia pewnych dodatkowych zasobów używanych przez obiekt. Metoda finalize()należy do klasy Object. Innymi słowy, jest podobny do equals(), hashCode()i toString()(których spotkałeś wcześniej). Każdy przedmiot to ma . Różni się od innych metod tym, że… jakby to powiedzieć… jest bardzo umyślna. Rozumiemy przez to, żenie zawsze jest wywoływana przed zniszczeniem obiektu . Programowanie to bardzo precyzyjna czynność. Programista każe komputerowi coś zrobić, a komputer to robi. Zakładam, że przyzwyczaiłeś się do tego rodzaju zachowań, więc na początku może ci być trudno zaakceptować następującą myśl: „Zanim obiekt zostanie zniszczony, metoda klasy Object jest wywoływana. Lub nie. finalize()Jeśli nam się poszczęści! " Jednak taka jest rzeczywistość. Maszyna Java sama określa, czy wywołać finalize() indywidualnie dla każdego przypadku. W ramach eksperymentu spróbujmy uruchomić następujący kod:

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;// The first object becomes available for garbage collection here
       }
   }

   @Override
   protected void finalize() throws Throwable {
       System.out.println("The Cat is destroyed!");
   }
}
Tworzymy Catobiekt, aw następnym wierszu wyzerowujemy jedyne odniesienie do niego. I robimy to milion razy. Wyraźnie zastąpiliśmy finalize()metodę. Za każdym razem, gdy Catobiekt jest niszczony, musi wyświetlić ciąg — w sumie milion razy. Ale nie! Dokładniej, na moim komputerze został wykonany tylko 37346 razy! Innymi słowy, moja maszyna Java zdecydowała się wywołać finalize()metodę tylko w 1 na 27 przypadków. W innych przypadkach wyrzucanie elementów bezużytecznych nie obejmowało tego wywołania. Spróbuj samodzielnie uruchomić ten kod. Najprawdopodobniej uzyskasz inny wynik. Jak widać trudno nazwać finalize()solidnym partnerem :) A więc mała wskazówka na przyszłość: nie polegaj na finalize()metodzie uwalniania krytycznych zasobów.JVM może to wywołać lub nie. Kto wie? Jeśli Twój obiekt posiadał pewne zasoby krytyczne dla wydajności (na przykład otwarte połączenie z bazą danych), gdy był aktywny, lepiej byłoby utworzyć i jawnie wywołać specjalną metodę, aby zwolnić je, gdy obiekt nie będzie już potrzebny. W ten sposób będziesz mieć pewność, że wydajność Twojego programu nie ucierpi. Zaczęliśmy od stwierdzenia, że ​​praca z pamięcią i usuwaniem elementów bezużytecznych to bardzo ważne tematy i rzeczywiście są. Niewłaściwe obchodzenie się z zasobami i nieporozumienie, w jaki sposób usuwane są niepotrzebne obiekty, może prowadzić do jednego z najbardziej nieprzyjemnych błędów: wycieków pamięci . To jeden z najbardziej znanych błędów programistycznych. Ma nawet własny artykuł w Wikipedii. Źle napisany kod może stworzyć sytuację, w której pamięć jest alokowana za każdym razem dla nowo tworzonych obiektów, ale stare, niepotrzebne obiekty są niedostępne do odśmiecania. Ponieważ zrobiliśmy już analogię robota odkurzającego, wyobraź sobie, co by się stało, gdybyś przed uruchomieniem robota rozrzucił skarpetki po całym domu, rozbił szklany wazon i zostawił klocki Lego na podłodze. Oczywiście robot będzie próbował coś zrobić, ale pewnego dnia się zablokuje.
Cykl życia obiektu - 3
Aby odkurzacz działał prawidłowo, należy utrzymywać podłogę w należytym stanie i zbierać wszystko, z czym nie poradzi sobie. Garbage collector działa na tej samej zasadzie. Jeśli program ma wiele obiektów, których nie może wyczyścić (jak skarpetka lub klocki Lego do naszego robota odkurzającego), pewnego dnia zabraknie nam pamięci. Nie tylko twój program się zawiesi, ale także wszystkie inne programy uruchomione na komputerze. W końcu im też zabraknie pamięci (wracając do naszej analogii, rozbite szkło na podłodze zatrzymuje nie tylko odkurzacz, ale i ludzi mieszkających w domu). Krótko mówiąc, tak wygląda cykl życia obiektów i wyrzucanie elementów bezużytecznych w Javie. Nie musisz tego zapamiętywać: wystarczy po prostu zrozumieć, jak to działa. Na następnej lekcji my Wrócę do tych procesów bardziej szczegółowo. Ale na razie możesz wrócić do rozwiązywania zadań CodeGym :) Powodzenia!
Komentarze
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION