Viimeistelijä

Jätteenkeräystä käyttävissä olio- ohjelmointikielissä viimeistely on erityinen menetelmä, jonka ajonaika kutsuu ennen kuin roskankerääjä hävittää objektin .

Määritelmä

Viimeistelijä on luokkametodi , jota ajonaika kutsuu automaattisesti sen hetken välillä, kun roskankerääjä tunnistaa kyseisen luokan objektin käyttämättömäksi ja sen jälkeen, kun objekti poistetaan (sen varaama muisti vapautetaan). Tietyn objektin viimeistely suoritetaan aina sen jälkeen, kun ohjelma lopettaa objektin käytön ja ennen kuin roskankerääjä vapauttaa objektin muistin. On kätevää ajatella, että viimeistelyä kutsutaan juuri ennen kuin objekti poistetaan muistista, vaikka tätä ei yleensä taata.

Ero tuhoajiin

Pinnalta katsottuna viimeistelylaite on samanlainen kuin luokan tuhoaja , mutta todellisuudessa näiden menetelmien vaikutus ja laajuus ovat melko erilaisia. Ero johtuu siitä, että viimeistelijän kutsumishetkeä, toisin kuin tuhoajaa, ei ole määritelty tiukasti: viimeistelyjä kutsutaan aina ennen kuin roskankerääjä tuhoaa kohteen, mutta tuhoamishetki riippuu käsittelytavasta. roskankeräimen toiminta, käytettävissä olevan RAM-muistin määrä ja ohjelman muistin käyttöaktiivisuus. Joten jos vapaata muistia on vähän ja uusia objekteja luodaan jatkuvasti, roskienkeräystarve esiintyy usein ja viimeistelyä vastaavasti kutsutaan erittäin todennäköisesti pian sen jälkeen, kun objektia ei enää käytetä. Jos muistia on paljon ja sen kulutus ohjelman toimesta on pieni, voi kestää kauan objektin käytön lopettamisesta roskien keräämiseen (ja viimeistelijan kutsuun). Lisäksi, jos muistia on paljon ja uusia objekteja luodaan vähän tai ei ollenkaan, roskankerääjää ei välttämättä kutsuta ollenkaan, ja ohjelman lopussa kaikki sille varattu muisti palautetaan yksinkertaisesti käyttöjärjestelmään. järjestelmä; tässä tapauksessa viimeistelijaa ei ehkä kutsuta ollenkaan.

Vaikka tuhoajia käytetään usein vapauttamaan objektin käyttämiä niukkoja järjestelmäresursseja (kuten pääsy tiedostoon tai laitteistoon ), viimeistelijöitä ei yleensä suositella käytettäväksi tällä tavalla yllä mainittujen ominaisuuksien vuoksi. Viimeistelijä voi tietysti sulkea tiedoston tai kertoa käyttöjärjestelmälle, että laite ei ole enää käytössä, mutta siitä hetkestä, kun objektia ei enää käytetä, voi kulua rajaton aika siihen hetkeen, kun viimeistelyä kutsutaan. koko tämän ajan kohteen käyttämiä resursseja ei käytetä, mutta ne ovat varattuina. [yksi]

Viimeistelyt ovat arvaamattomia, usein vaarallisia ja usein tarpeettomia.

- Joshua Bloch. Tehokas Java. Addison-Westley, 2001.

Yllä olevan seurauksena viimeistelijöiden käyttö on hyvin rajallista. Jätekerätyt kielet käyttävät "hävitä" -suunnittelumallia resurssien jakamiseen . C# -ohjelmointikieli tukee " dispose" -mallia implisiittisesti käyttöliittymän ja avainsanan kautta , ja Java 7 esitteli samanlaisen "try with-resurss" -mekanismin. IDisposableusing

Perusteltu käyttö

Yksi harvoista tapauksista, joissa viimeistely on todella tarpeen, on, kun luokka toteuttaa omia muistinkäsittelymekanismejaan, jotka perustuvat kolmannen osapuolen koodiin , jota roskankeräysjärjestelmä ei hallitse , esimerkiksi kun Java-luokka käyttää C-kielellä kirjoitettua koodia saavuttaakseen maksimaalista tehoa tai suorittaa matalan tason toimintoja. Jotta ulkoinen koodi toimisi, muisti on varattava tavallisilla C-mekanismeilla (malloc) ja vapautettava niiden omalla avulla (ilmainen). Voit (ja yleensä pitäisi) kutsua muistinvarausfunktiota luokkakonstruktorissa, ja oikea paikka ulkoisen muistin purkamisfunktion kutsumiseen on viimeistelyssä, koska tämä paikka varmistaa, että ulkoisen koodin muisti varataan ennen objektia. käytetään (kun se luotiin) ja vapautetaan vain, kun sen käyttö loppuu. Jos viimeistelyä ei kutsuta heti tai sitä ei kutsuta ollenkaan, mitään pahaa ei tapahdu, koska varattu ulkoinen muisti palautetaan edelleen järjestelmään automaattisesti ohjelman päätyttyä.

Toinen hyvä tapa käyttää viimeistelytyökalua on varmistaa, että objekti on siivottu ennen poistamista. Jos objekti kaappaa luomisen tai toiminnan aikana muita arvokkaita järjestelmäresursseja kuin muistia (avaa tiedostoja tai viestintäkanavia, muodostaa yhteyden I/O-laitteisiin), niin on selvää, että sillä hetkellä, kun roskankerääjä poistaa kohteen, Kaikki nämä resurssit pitäisi jo vapauttaa (siis on puhdistettava kohde). Puhdistusvirheet (kun esinettä joissain tilanteissa ei puhdisteta tai, mikä vielä pahempaa, ei puhdisteta kokonaan) ovat erittäin salakavalia, niitä on vaikea havaita, koska ne ilmenevät suoritettaessa täysin erilaista koodin osaa, jossa virhe tapahtui. tehty. Kuten jo mainittiin, ei ole viisasta siivota viimeistelyssä, koska ei tiedetä milloin se kutsutaan ja kutsutaanko sitä ollenkaan. Mutta viimeistelyssä on varsin sopivaa ja kätevää tarkistaa, onko objekti täysin tyhjennetty, ja antaa tavalla tai toisella virheilmoitus, jos jokin resurssi jää kaapatuksi. Sillä ei ole väliä, että viimeistelyä voidaan kutsua myöhään eikä joka kerta; joka tapauksessa, jos objektin siivoamisessa on virhe, niin viimeistelylaite ennemmin tai myöhemmin "saavaa" sen kiinni.

Esimerkkejä

Finalisoijat voidaan luoda eri tavoin. Joillakin kielillä viimeistely on osa vakiokirjastoa. Yleensä tällaisissa tapauksissa kyseessä on tavallisen juuriluokan virtuaalinen menetelmä, josta kaikki muut järjestelmän luokat ovat jälkeläisiä ( Javassa tämä on Object-luokan finalize () -metodi). Viimeistelyt voidaan myös ilmoittaa käyttämällä erityistä syntaksia. C# : ssa viimeistelyn ilmoittamisen syntaksi on lainattu C++ -destruktoreista - Class-luokan viimeistelystä tulee menetelmä, jossa on ~Class()-allekirjoitus. C# : aan perustuva Nemerle- kieli hylkäsi tämän syntaksin, koska sitä pidettiin virhealttiina.

Muistiinpanot

  1. Raymond Chen. Ajattelet varmasti roskien keräämistä väärin . Arkistoitu 19. heinäkuuta 2013 Wayback Machinessa

Kirjallisuus