Véglegesítő

A szemétgyűjtést használó objektum-orientált programozási nyelvekben a véglegesítő egy speciális módszer, amelyet a futási környezet hív meg, mielőtt a szemétgyűjtő egy objektumot megsemmisít.

Definíció

A véglegesítő egy olyan osztálymetódus , amelyet a futási környezet automatikusan hív meg az adott osztály objektumának a szemétgyűjtő általi használaton kívüliként való felismerése és az objektum eltávolítása (az általa elfoglalt memória felszabadítása) között . Egy adott objektum véglegesítése mindig lefut, miután a program már nem használja az objektumot, és mielőtt a szemétgyűjtő felszabadítaná az objektum memóriáját. Kényelmes úgy gondolni, hogy a véglegesítő közvetlenül az objektum memóriából való eltávolítása előtt hívódik meg, bár ez általában nem garantált.

Különbség a destruktoroktól

A felületen a véglegesítő hasonlít egy osztályrombolóhoz , de a valóságban ezeknek a módszereknek a hatása és hatóköre egészen más. A különbség abból adódik, hogy a véglegesítő meghívásának pillanata a destruktorral ellentétben nincs mereven definiálva: a véglegesítőt mindig azelőtt hívják meg, hogy a szemétgyűjtő megsemmisítené az objektumot, de a megsemmisítés pillanata függ a megsemmisítés módjától. a szemétgyűjtő működését, a rendelkezésre álló RAM mennyiségét és a program memóriahasználati tevékenységét. Tehát, ha kevés a szabad memória, és folyamatosan új objektumok létrehozása történik, akkor gyakran van szükség a szemétgyűjtésre, és ennek megfelelően nagy valószínűséggel a véglegesítő hamarosan meghívásra kerül, miután az objektumot már nem használják. Ha sok a memória, és a program általi felhasználása kicsi, akkor az objektum használatának megszűnésétől a szemétgyűjtésig (és a véglegesítő hívásáig) sok idő telhet el. Sőt, ha sok a memória, és kevés vagy egyáltalán nem jön létre új objektum, akkor előfordulhat, hogy a szemétgyűjtő egyáltalán nem hívható meg, és a program végén az összes hozzárendelt memória visszakerül az operációs rendszerbe. rendszer; ebben az esetben előfordulhat, hogy a véglegesítő egyáltalán nem hívható meg.

Míg a destruktorokat nagyon gyakran használják az objektumok által elfoglalt szűkös rendszererőforrások (például egy fájlhoz vagy hardverhez való hozzáférés ) felszabadítására, a véglegesítőket a fent említett jellemzők miatt általában nem javasoljuk ilyen módon használni. Természetesen a véglegesítő bezárhatja a fájlt, vagy közölheti az operációs rendszerrel , hogy az eszköz már nincs használatban, azonban meghatározatlan idő telhet el attól a pillanattól kezdve, amikor az objektumot már nem használják, és a véglegesítő meghívásának pillanatáig. ez idő alatt az objektum által elfoglalt erőforrások nem kerülnek felhasználásra, hanem foglaltak maradnak. [egy]

A véglegesítők kiszámíthatatlanok, gyakran veszélyesek és gyakran szükségtelenek is.

– Joshua Bloch. Hatékony Java. Addison-Westley, 2001.

A fentiek következtében a véglegesítők használata nagyon korlátozott. A szemétgyűjtő nyelvek a „megsemmisítés” tervezési mintát használják az erőforrások felosztására . A C# programozási nyelv az interfészen IDisposable és a kulcsszón keresztül implicit módon támogatja a "dispose" mintát, a usingJava 7 pedig egy hasonló "try-with-resources" mechanizmust vezetett be.

Indokolt használat

Az egyik ritka eset, amikor valóban szükség van véglegesítőre, az az, amikor egy osztály saját memóriakezelési mechanizmusait valósítja meg, amelyek harmadik féltől származó kódra támaszkodnak, amelyet nem a szemétgyűjtő rendszer kezel , például amikor egy Java osztály C-ben írt kódot használ az eléréshez. maximális hatékonyságot, vagy alacsony szintű műveleteket hajt végre. A külső kód működéséhez a memóriát szabványos C-mechanizmusokkal (malloc) kell lefoglalni, és saját segítségükkel fel kell szabadítani (ingyenes). Meghívhatja (és általában meg is kell) a memóriafoglalási függvényt az osztálykonstruktorban, és a külső memóriafelszabadító függvény hívásának megfelelő helye a véglegesítőben található, mivel ez a hely biztosítja, hogy a külső kód memóriája az objektum előtt kerül lefoglalásra. használatban van (amikor létrehozták), és csak akkor adják ki, ha a használat megszűnik. Ha a véglegesítőt nem hívják meg azonnal, vagy egyáltalán nem hívják meg, semmi rossz nem történik, mivel a lefoglalt külső memória a program lejárta után is automatikusan visszakerül a rendszerbe.

A véglegesítő használatának egy másik jó módja annak biztosítása, hogy az objektumokat a törlés előtt megtisztítsák. Ha egy objektum a létrehozás során vagy működése során a memórián kívül értékes rendszererőforrásokat rögzít (fájlokat vagy kommunikációs csatornákat nyit meg, I/O eszközökhöz csatlakozik), akkor nyilvánvalóan abban a pillanatban, amikor az objektumot a szemétgyűjtő törli, ezeket az erőforrásokat már fel kell szabadítani (akkor van egy objektum, amit törölni kell). A tisztítási hibák (amikor az objektumot bizonyos helyzetekben nem, vagy ami még rosszabb, nem tisztítják meg teljesen) nagyon alattomosak, nehezen észlelhetők, mivel a kód egy teljesen más részének végrehajtásakor jelennek meg, ahol a hiba történt. készült. Mint már említettük, nem bölcs dolog a véglegesítőben takarítani, mivel nem tudni, hogy mikor hívják, és hogy egyáltalán hívják-e. De a véglegesítőben meglehetősen helyénvaló és kényelmes ellenőrizni, hogy az objektum teljesen törölve van-e, és valamilyen formában hibaüzenetet ad ki, ha valamilyen erőforrás továbbra is rögzítve marad. Nem számít, hogy a véglegesítőt későn hívják, és nem minden alkalommal; amúgy ha objektumtisztítási hiba van, akkor előbb-utóbb a véglegesítő „elkapja”.

Példák

A véglegesítők különböző módon hozhatók létre. Egyes nyelveken a véglegesítő a szabványos könyvtár része. Általában ilyen esetekben a szabványos gyökérosztály virtuális metódusáról van szó, amelyből a rendszerben lévő összes többi osztály leszármazottja ( Java-ban ez az Object osztály finalize () metódusa). A véglegesítők speciális szintaxissal is deklarálhatók. A C# nyelvben a véglegesítő deklarálására szolgáló szintaxis a C++ destruktoroktól kölcsönzött - a Class osztály véglegesítője a ~Class() aláírású metódus lesz. A C#-on alapuló Nemerle nyelv elhagyta ezt a szintaxist, mert hibásnak tartották.

Jegyzetek

  1. Raymond Chen. Biztosan a szemétszállításra gondolsz rosszul . Archivált : 2013. július 19., a Wayback Machine

Irodalom