Szia! Az utolsó leckében először a Java beépített szemétgyűjtőjével ismerkedtünk meg, és nagyjából képet kaptunk a működéséről. A program futása közben a háttérben működik, és összegyűjti a szükségtelen objektumokat, amelyek később törlődnek. Így felszabadítja a memóriát, amelyet a jövőben új objektumok létrehozására lehet használni.
Bővebben a szemétgyűjtőről - 1
Ebben a leckében részletesebben megvitatjuk, hogyan működik. Például hogyan és mikor válik szükségtelenné egy tárgy? És honnan tudja meg a szemétszállító? Ezekre a kérdésekre fogunk válaszolni a mai órán :) A lecke inkább egy áttekintés lesz: nem kell fejből megtanulni ezt az anyagot. A cél elsősorban a memória és a szemétgyűjtő működésével kapcsolatos látásmód bővítése, úgyhogy csak olvassa el és találjon valami újat a maga számára :) Gyerünk! Az első dolog, amit emlékezned kell, hogy a szemétgyűjtő párhuzamosan működik a programoddal. Nem része a programodnak. Külön működik (az utolsó leckében ezt egy robotporszívóhoz hasonlítottuk) De nem mindig volt így. A szemétgyűjtés régebben ugyanazon a szálon történt, mint a programod. Bizonyos ütemterv szerint (néhány percenként egyszer) a szemétgyűjtő ellenőrizte a nem kívánt objektumok jelenlétét a programban. A probléma az volt, hogy a program lefagy (nem fut le) az ellenőrzés és a szemétgyűjtés során. Képzelje el, hogy az irodájában ül a munkahelyén. De aztán bejön a takarítónő padlót mosni. 5 percre elviszi a számítógépétől, és megvárja, amíg befejezi a takarítást. Ez idő alatt nem tud dolgozni. Körülbelül így működött régen a szemétszedés :) Ez a mechanizmus később megváltozott, és most a szemétszedő fut a háttérben, nem akadályozza magának a programnak a munkáját. Már tudja, hogy egy objektum akkor hal meg, amikor már nincs hivatkozása. A valóságban,a szemétgyűjtő nem számolja az objektum hivatkozásokat . Először is, ez sokáig tarthat. Másodszor, nem túl hatékony. Hiszen a tárgyak utalhatnak egymásra! Bővebben a szemétgyűjtőről - 2Az ábrán egy példa látható, ahol 3 objektum utal egymásra, de senki más nem hivatkozik rájuk. Más szóval, a program többi részének nincs szüksége rájuk. Ha a szemétgyűjtő egyszerűen számolná a hivatkozásokat, akkor ez a 3 objektum nem kerülne begyűjtésre és a memória sem szabadulna fel (van rájuk hivatkozás!). Ezt egy űrhajóhoz hasonlíthatjuk. Repülés közben az űrhajósok úgy döntenek, hogy megnézik a javítható alkatrészek listáját. Többek között kormányt és pedálokat találnak egy közönséges autóból. Nyilvánvalóan itt nincs rájuk szükség, és feleslegesen foglalják a helyet (bár ez a két rész összefügg egymással, és van néhány funkciója). De az űrszondán belül ezek haszontalan szemét, amelyet el kell dobni. Ennek megfelelően Javaban nem referenciaszámlálás alapján döntöttek a szemétgyűjtés mellett,elérhető és elérhetetlen . Hogyan határozzuk meg, hogy egy tárgy elérhető-e? Az egész egyszerűen zseniális. Egy objektum akkor érhető el, ha egy másik elérhető objektum hivatkozik rá. Így egy "elérhetőségi láncot" kapunk. Akkor kezdődik, amikor a program elindul, és a program időtartama alatt folytatódik. Valahogy így néz ki: Bővebben a szemétgyűjtőről - 3 Az ábrán látható nyíl a programunk végrehajtható kódját jelzi. A kód (például a main()metódus) hivatkozásokat hoz létre az objektumokra. Ezek az objektumok hivatkozhatnak más objektumokra, ezek az objektumok ismét másokra, és így tovább. Ez egy referencialáncot alkot. Ha egy objektumtól a "gyökérreferenciáig" (amely közvetlenül a végrehajtható kódban jött létre), akkor az elérhetőnek tekinthető. Az ilyen tárgyak a képen feketén vannak jelölve. De egy objektum elérhetetlen, ha az objektum kiesik ebből a láncból, azaz az éppen végrehajtott kód egyik változója sem hivatkozik rá, és nem érhető el a "referencialáncon" keresztül. Programunkban két ilyen objektumot pirossal jelölünk. Vegye figyelembe, hogy ezek a "piros" objektumok egymásra utalnak. De ahogy korábban mondtuk, a Java modern szemétgyűjtője nem számolja a hivatkozásokat. Meghatározza, hogy egy objektum elérhető vagy nem elérhető. Ennek eredményeként megragadja az ábrán látható két piros tárgyat. Most nézzük meg az egész folyamatot az elejétől a végéig. Ennek során azt is látni fogjuk, hogyan van elrendezve a memória a Java-ban :) Minden Java objektum a memória egy speciális területén, a kupacban van tárolva . A köznyelvben a kupac általában tárgyak hegye, ahol minden keveredik. De nem ez a kupac a Java-ban. Felépítése nagyon logikus és ésszerű. Valamikor a Java programozók úgy találták, hogy minden objektumukat két típusra lehet osztani: egyszerű objektumokra és "hosszú életű objektumokra".. A "hosszú életű tárgyak" olyan tárgyak, amelyek több szemétgyűjtést is túléltek. Általában a program végéig élnek. Végül a teljes kupacot, ahol minden tárgyat tárolnak, több részre osztották. Az első résznek szép neve van: éden(a bibliai "Édenkertből"). Ez a név illik, mert ide kerülnek az objektumok létrehozásuk után. Ez a memória azon része, ahol új objektumok jönnek létre, ha az új kulcsszót használjuk. Sok objektum jöhet létre. Amikor ezen a területen elfogy a hely, megkezdődik a kezdeti "gyors" szemétgyűjtés. Azt kell mondanunk, hogy a szemétszedő nagyon ügyes. Az alapján választ ki egy algoritmust, hogy a halomban több a szemét vagy több élő objektum. Ha szinte minden tárgy szemét, a gyűjtő megjelöli az élő objektumokat, és áthelyezi őket a memória egy másik területére. Ezután az aktuális terület teljesen kiürül. Ha nincs sok szemét, és a kupac többnyire élő tárgyakból áll, akkor a gyűjtő megjelöli a szemetet, eltakarítja, és a többi tárgyat összecsomagolja. Azt mondtuk "túlélési tér . A túlélési tér pedig generációkra oszlik . Minden tárgy egy adott generációhoz tartozik, attól függően, hogy hány szemétgyűjtési kört élt túl. Ha egy tárgy túlélt egy szemétgyűjtési kört, akkor az "1. generációba" tartozik; ha 5, akkor "5. generáció". Az éden és a túlélési tér együtt alkotják a fiatal generációnak nevezett területet . A halomnak a fiatal generáción kívül van egy másik emlékezeti területe is, az úgynevezett régi generáció. Pontosan erre a területre kerülnek a sok szemétgyűjtést átvészelt, hosszú életű tárgyak. Előnyökkel jár, ha elkülönítjük őket az összes többitől. A teljes szemétgyűjtés csak akkor történik meg, ha a régi generáció megtelt, azaz annyi hosszú életű objektum van a programban, hogy nincs elég memória. Ez a folyamat a memória egynél több területét érinti. Általában a Java gép által létrehozott összes objektumot magában foglalja. Természetesen ez sokkal több időt és erőforrást igényel. Pontosan ez a döntés született a hosszú élettartamú tárgyak elkülönített tárolásáról. A "gyors szemétszállítás" akkor történik, ha más területeken elfogy a hely. Ez csak egy területet érint, ami gyorsabbá és hatékonyabbá teszi. Végül, amikor még a hosszú élettartamú tárgyak területe is teljesen megtelt, teljes szemétszállítás indul. Így a gyűjtő csak akkor használja a "legnehezebb" eszközt, ha azt lehetetlen elkerülni. Íme a kupacszerkezet és a szemétgyűjtés vizuális ábrázolása: Bővebben a szemétgyűjtőről - 4