CodeGym /Java blog /Véletlen /Az objektum életciklusa
John Squirrels
Szint
San Francisco

Az objektum életciklusa

Megjelent a csoportban
Szia! Szerintem nem lepődnél meg nagyon, ha azt mondanám, hogy a számítógépednek korlátozott a memóriája :)
Az objektum életciklusa – 1
Még a merevlemezed is (amely sokszorosa a RAM-nak) megtelhet kedvenc játékaiddal, tévéműsoraiddal és egyéb dolgokkal. Ennek elkerülése érdekében figyelnie kell a számítógép memóriájának aktuális állapotát, és törölnie kell a szükségtelen fájlokat. Hogyan kapcsolódik mindez a Java programozáshoz? Egészen közvetlenül! Végül is bármilyen objektum létrehozása azt eredményezi, hogy a Java gép memóriát foglal le számára . Egy nagy valós program több tíz- vagy százezer objektumot hoz létre, és mindegyikhez egy-egy memóriadarabot foglalnak le. De mit gondolsz, hány ilyen tárgy létezik? „Élnek” mindaddig, amíg a programunk fut? Természetesen nem. A Java objektumok még minden előnyük ellenére sem halhatatlanok :) Az objektumok saját életciklussal rendelkeznek. Ma egy kis szünetet tartunk a kódírásban, és megvizsgáljuk ezt a folyamatot :) Ez nagyon fontos a program működésének megértéséhez és az erőforrások kezeléséhez is. Tehát hol kezdődik egy tárgy élete? Mint az ember, születésétől, azaz amikor létrejött.

Cat cat = new Cat();// Our Cat object's lifecycle begins now!
Először a Java virtuális gép lefoglalja az objektum létrehozásához szükséges memóriát. Ezután hivatkozást hoz létre rá (esetünkben cat), hogy nyomon tudja követni. Ezután az összes változó inicializálódik, a konstruktor meghívásra kerül, és a friss objektumunk most éli a saját életét :) Az objektumok élettartama változó. Itt nincsenek pontos adatok. Mindenesetre egy objektum a programban él, és bizonyos ideig ellátja funkcióit. Hogy pontosak legyünk, az objektum addig "él", amíg vannak rá hivatkozások. Amint nincs hivatkozás, az objektum "elhal". Például:

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;

   }

}
A módszerben main()a "Lamborghini Diablo" Car objektum a második sorban megszűnik élni. Csak egy hivatkozás volt rá, és a hivatkozás nullára lett állítva. Mivel a Diablo-ra már nincs utalás, "szemétté" válik. A hivatkozást nem kell nullára állítani, hogy ez megtörténjen:

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;
   }

}
Itt létrehoztunk egy második objektumot, és hozzárendeltük a lamborghini hivatkozáshoz. Most két hivatkozás mutat az objektumra Lamborghini Gallardo, de az Lamborghini Diabloobjektumnak nincs. Ez azt jelenti, hogy az Diabloobjektum szemétté válik. Ekkor lép működésbe a Java beépített szemétgyűjtője (GC).
Az objektum életciklusa – 2
A szemétgyűjtő egy belső Java-mechanizmus, amely a memória felszabadításáért, azaz a szükségtelen objektumok eltávolításáért felelős. Megvan az oka annak, hogy úgy döntöttünk, hogy egy robotporszívóval képviseljük. A szemétgyűjtő nagyjából ugyanígy működik: a háttérben "mozgatja" a programodat, gyűjti a szemetet. Gyakorlatilag nem kell kapcsolatba lépni vele. Feladata a programban már nem használt objektumok törlése. Így memóriát szabadít fel más objektumok számára. Emlékszel, hogy a lecke elején azt mondtuk, hogy a való életben figyelnie kell a számítógép állapotát, és törölnie kell a régi fájlokat? Ha Java objektumokról beszélünk, akkor ezt a szemétgyűjtő végzi el helyetted. A szemétgyűjtő a program futása közben sokszor elindul: nem kell kifejezetten meghívnia és parancsokat adnia (bár ez technikailag lehetséges). A szemétgyűjtőről később bővebben szólunk, és részletesebben elemezzük a működését. Amikor a szemétgyűjtő elér egy objektumot – közvetlenül azelőtt, hogy megsemmisülne – az objektum speciális finalize()metódusa hívódik meg. Ez a metódus meghívható bizonyos, az objektum által használt további erőforrások felszabadítására. A finalize()metódus az Object osztályba tartozik. Más szóval, hasonló a equals(), hashCode()és -hez toString()(amivel korábban már találkozott). Minden tárgynak megvan . Abban különbözik a többi módszertől...hogy is mondjuk ezt...nagyon akaratos. Ez alatt azt értjüknem mindig hívják meg egy objektum megsemmisítése előtt . A programozás nagyon precíz tevékenység. A programozó utasítja a számítógépet, hogy csináljon valamit, és a számítógép megteszi. Feltételezem, hogy megszoktad ezt a fajta viselkedést, így elsőre nehéz lehet elfogadnod a következő gondolatot: "Mielőtt egy objektum megsemmisül, az Object osztály metódusa hívódik meg. Vagy nem. Ha szerencsénk lesz finalize()! " Mégis, ez a valóság. A Java gép maga dönti el, hogy meg kell-e hívni a finalize() függvényt, eseti alapon. Kísérletként próbáljuk meg futtatni a következő kódot:

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!");
   }
}
Létrehozunk egy Catobjektumot, és a következő sorban nullázzuk az egyetlen hivatkozást. És ezt milliószor megtesszük. Kifejezetten felülírtuk a finalize()módszert. Minden alkalommal, amikor egy Catobjektum megsemmisül, egy karakterláncot kell megjelenítenie – összesen egymilliószor. De nem! Pontosabban, az én számítógépemen mindössze 37346 alkalommal hajtották végre! Más szóval, a Java gépem finalize()27 esetből csak 1 esetben döntött úgy, hogy meghívja a metódust. A többi esetben a szemétszállítás nem járt ezzel a felhívással. Próbálja meg saját maga futtatni ezt a kódot. Valószínűleg más eredményt fog kapni. Amint látja, nehéz finalize()megbízható partnert hívni :) Szóval, egy kis tipp a jövőre nézve: ne hagyatkozz a finalize()módszerre a kritikus erőforrások felszabadítása érdekében.Lehet, hogy a JVM hívja, vagy nem. Ki tudja? Ha az objektum működése során bizonyos teljesítménykritikus erőforrásokat (például nyitott adatbázis-kapcsolatot) tartalmazott, jobb lenne létrehozni és kifejezetten meghívni egy speciális metódust, amely felszabadítja azokat, amikor az objektumra már nincs szükség. Így biztosan tudni fogja, hogy programja teljesítménye nem fog csorbulni. Azzal kezdtük, hogy a memóriával való munka és a szemétszállítás nagyon fontos téma, és valóban az is. Az erőforrások helytelen kezelése és a szükségtelen objektumok tisztításának félreértése az egyik legkellemetlenebb hibához vezethet: memóriaszivárgáshoz . Ez az egyik legismertebb programozási hiba. Még saját Wikipédiás cikke is van. A rosszul megírt kód olyan helyzetet teremthet, amikor a memória minden alkalommal lefoglalódik az újonnan létrehozott objektumokhoz, de a régi, szükségtelen objektumok nem érhetők el a szemétgyűjtéshez. Mivel már elkészítettük a robotporszívó hasonlatát, képzelje el, mi történne, ha a robot elindítása előtt zoknikat szórna szét a házban, összetörne egy üvegvázát, és lego darabokat hagyna a padlón. Természetesen a robot megpróbálna tenni valamit, de egy nap megfogja.
Az objektum életciklusa – 3
Ahhoz, hogy a porszívó megfelelően működjön, megfelelő állapotban kell tartania a padlót, és fel kell szednie mindent, amit nem tud kezelni. A szemétgyűjtő ugyanezt az elvet követi. Ha egy programnak sok olyan tárgya van, amelyet nem tud megtisztítani (például egy zoknit vagy legót a robotporszívónkhoz), egy nap elfogy a memóriánk. Nem csak a program lefagy, hanem a számítógépen futó összes többi program is. Hiszen nekik sem lesz elég memóriájuk (hasonlatunkhoz visszatérve, a padlón lévő törött üveg nemcsak a porszívót állítja meg, hanem az otthon lakókat is). Röviden, így néz ki az objektumok életciklusa és a szemétgyűjtés a Java-ban. Ezt nem kell memorizálnia: elég, ha egyszerűen megérti, hogyan működik. A következő leckében mi részletesebben visszatérek ezekre a folyamatokra. De egyelőre visszatérhetsz a CodeGym feladatok megoldásához :) Sok sikert!
Hozzászólások
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION