Există un destructor pentru Java? (Programare, Java, Colectarea Gunoiului, Destructor)

wai a intrebat.

Există un destructor pentru Java? Se pare că nu pot găsi nicio documentație în acest sens. Dacă nu există, cum pot obține același efect?

Pentru a face întrebarea mea mai specifică, scriu o aplicație care se ocupă de date, iar specificațiile spun că ar trebui să existe un buton de „resetare” care să readucă aplicația la starea inițială, abia lansată. Cu toate acestea, toate datele trebuie să fie „vii”, cu excepția cazului în care aplicația este închisă sau butonul de resetare este apăsat.

Fiind de obicei un programator C/C++, am crezut că acest lucru ar fi simplu de implementat. Mi-am structurat programul astfel încât toate obiectele „resetabile” să fie în aceeași clasă, astfel încât să pot distruge toate obiectele „vii” atunci când este apăsat un buton de resetare.

Mă gândeam că dacă tot ce am făcut a fost doar să dereferențiez datele și să aștept ca garbage collector-ul să le colecteze, nu ar exista o scurgere de memorie dacă utilizatorul meu ar introduce în mod repetat date și ar apăsa butonul de resetare? De asemenea, mă gândeam că, deoarece Java este un limbaj destul de matur ca limbaj, ar trebui să existe o modalitate de a preveni acest lucru sau de a rezolva în mod grațios această problemă.

Comentarii

  • Există o scurgere de memorie doar dacă dețineți referințe la obiecte de care nu aveți nevoie. adică Există o eroare în programul dvs. GC va rula în funcție de necesități (uneori mai devreme) –  > Por Peter Lawrey.
  • 19

  • Mașina virtuală nu va rula GC suficient de repede dacă procesați rapid date prin intermediul obiectelor. Ideea că GC poate ține întotdeauna pasul sau că poate lua deciziile corecte este o eroare. –  > Por Kieveli.
  • @Kieveli JVM nu ar rula GC înainte de a da o eroare? –  > Por WVrock.
  • Da, ar fi frumos dacă ar exista un destructor pentru Java care să-l distrugă o dată pentru totdeauna. –  > Por Tomáš Zato – Reinstaurați-o pe Monica.
  • @WVVrock – Interesantă întrebare. Răspunsul este „nu” (cel puțin pentru anumite tipuri de „procesare rapidă a datelor prin obiecte”), dar dintr-un motiv nuanțat. Eroarea reală pe care o obțineți apare atunci când petreceți ceva de genul 97% din timp în colectarea gunoiului și doar 3% pe logica reală a programului, deoarece majoritatea referințelor încă au pointeri care conduc în ele. Dacă „procesarea rapidă” folosește un număr mic de pointeri, nu va exista nicio problemă. –  > Por sf_jeff.
22 răspunsuri
Garth Gilmour

Deoarece Java este un limbaj cu colectare de gunoi, nu puteți prezice când (sau chiar dacă) un obiect va fi distrus. Prin urmare, nu există un echivalent direct al unui destructor.

Există o metodă moștenită numită finalize, , dar aceasta este apelată în întregime la discreția colectorului de gunoi. Prin urmare, pentru clasele care trebuie să facă ordine în mod explicit, convenția este de a defini o metodă close și să se folosească finalize doar pentru verificarea corectitudinii (adică dacă close nu a fost apelată, faceți-o acum și înregistrați o eroare).

A existat recent o întrebare care a generat o discuție aprofundată despre finalize, așa că ar trebui să ofere mai multă profunzime, dacă este necesar…

Comentarii

  • Se referă „close()” în acest context la metoda din java.lang.Autocloseable? –  > Por Sridhar Sarnobat.
  • 21

  • Nu, AutoCloseable a fost introdusă în Java 7, dar convenția „close()” există de mult mai mult timp. –  > Por Jon Onstott.
  • de ce nu se poate prezice când (sau chiar dacă) un obiect va fi distrus. ce altă modalitate aproximativă de a prezice acest lucru? – utilizator1270589
  • @dctremblay distrugerea obiectelor se face de către garbage collector și este posibil ca garbage collector să nu ruleze niciodată pe durata de viață a aplicației. –  > Por Piro spune Reinstaurați-o pe Monica.
  • Rețineți că finalize metoda a fost depreciată în Java 9. –  > Por Lii.
Vitalii Fedorenko

Aruncați o privire la try-with-resources declarație. De exemplu:

try (BufferedReader br = new BufferedReader(new FileReader(path))) {
  System.out.println(br.readLine());
} catch (Exception e) {
  ...
} finally {
  ...
}

Aici, resursa care nu mai este necesară este eliberată în BufferedReader.close() metoda . Puteți crea o clasă proprie care să implementeze AutoCloseable și să o utilizați într-un mod similar.

Această declarație este mai limitată decât finalize în ceea ce privește structurarea codului, dar, în același timp, face codul mai simplu de înțeles și de întreținut. De asemenea, nu există nicio garanție că o finalize metoda este apelată deloc în timpul de viață al aplicației.

Comentarii

  • Sunt surprins că acest lucru are atât de puține voturi. Este răspunsul real. –  > Por nurettin.
  • 26

  • Nu sunt de acord că acesta este răspunsul real. Dacă o instanță are o resursă pe care o gestionează pe o perioadă mai mare de timp, pe parcursul mai multor apeluri de metode, atunci try-with-resources nu va fi de ajutor. Cu excepția cazului în care nu este în regulă să închizi și să redeschizi respectiva resursă în ritmul în care metodele respective sunt apelate – nu este un fapt general. –  > Por Eric.
  • 15

  • Într-adevăr, aceasta este nu răspunsul real. Este imposibil să se utilizeze această structură pentru a gestiona distrugerea unui obiect, cu excepția cazului în care construcția și utilizarea obiectului este în întregime încapsulată de structura try și finally este utilizat pentru a forța un apel la obj.finalize(). Și chiar și această configurație nu rezolvă problema pusă de OP: distrugerea obiectului în mijlocul programului declanșată de un buton de „resetare”. –  > Por 7yl4r.
  • Alți utilizatori au arătat că acest lucru se face în punctul de intrare al aplicației. Definiți variabila la nivel global. Inițializați-o în funcția de intrare, cu try. Dezinitializați-o la finally (când aplicația se închide). Este posibil în totalitate. –  > Por TamusJRoyce.
  • @nurettin Java 7 fusese lansat doar de 3 luni când a fost pusă întrebarea, dacă asta ajută la o mai bună înțelegere. –  > Por corsiKa.
ddimitrov

Nu, nu există destructori aici. Motivul este că toate obiectele Java sunt alocate în heap și colectate la gunoi. Fără o dezalocare explicită (de exemplu, operatorul de ștergere din C++), nu există o modalitate rezonabilă de a implementa destructori reali.

Java suportă finalizatori, dar aceștia sunt destinați să fie utilizați doar ca o protecție pentru obiectele care dețin un mâner la resurse native, cum ar fi socket-uri, mânere de fișiere, mânere de ferestre etc. Atunci când garbage collector colectează un obiect fără un finalizator, acesta marchează pur și simplu regiunea de memorie ca fiind liberă și atât. Atunci când obiectul are un finalizator, acesta este mai întâi copiat într-o locație temporară (nu uitați că aici este vorba de colectarea gunoiului), apoi este pus în coadă de așteptare pentru a fi finalizat și apoi un fir de finalizare interoghează coada cu prioritate foarte mică și execută finalizatorul.

Atunci când aplicația iese, JVM se oprește fără să aștepte ca obiectele în așteptare să fie finalizate, astfel încât nu există practic nicio garanție că finalizatorii dvs. vor fi executați vreodată.

Comentarii

  • Vă mulțumim pentru că ați menționat resursele native – acesta este un domeniu în care o metodă de tip „destructor” este utilă. –  > Por Nathan Osman.
  • da, mă confrunt cu aceeași problemă chiar acum cu eliberarea resurselor / mânerelor alocate prin apeluri native către C++. –  > Por nikk.
  • @ddimitrov, în teorie, ar putea java să implementeze dezalocarea explicită? Sau este aceasta o contradicție logică? –  > Por mils.
  • @mils implementarea naivă a dezalocării explicite ar încălca fie ipoteza Java conform căreia orice referință indică un obiect viu. Ați putea itera peste toți indicatorii și să anulați aliasurile, dar acest lucru este mai costisitor decât GC. Sau puteți încerca să folosiți un sistem de tip liniar (a se vedea „ownership” în Rust), dar aceasta reprezintă o schimbare majoră a limbajului. Există și alte opțiuni (a se vedea JavaRT scoped memory etc.), dar, în general, dezalocarea explicită nu se potrivește bine cu limbajul Java. –  > Por ddimitrov.
McDowell

Utilizarea de finalize() trebuie evitată. Acestea nu reprezintă un mecanism fiabil de curățare a resurselor și este posibil să se cauzeze probleme în cadrul colectorului de gunoi prin utilizarea lor abuzivă.

Dacă aveți nevoie de un apel de dezalocare în obiectul dumneavoastră, de exemplu pentru a elibera resurse, utilizați un apel explicit la o metodă. Această convenție poate fi observată în API-urile existente (de ex. Closeable, , Graphics.dispose(), , Widget.dispose()) și este de obicei apelată prin try/finally.

Resource r = new Resource();
try {
    //work
} finally {
    r.dispose();
}

Încercările de a utiliza un obiect eliminat ar trebui să arunce o excepție în timpul execuției (a se vedea IllegalStateException).


EDIT:

Mă gândeam că, dacă tot ce am făcut a fost doar să dereferențiez datele și să aștept ca garbage collector-ul să le colecteze, nu ar exista o scurgere de memorie dacă utilizatorul meu a introdus în mod repetat date și a apăsat butonul de resetare?

În general, tot ce trebuie să faceți este să dereferențiați obiectele – cel puțin așa ar trebui să funcționeze. Dacă sunteți îngrijorat de colectarea gunoiului, consultați Java SE 6 HotSpot[tm] Virtual Machine Garbage Collection Tuning (în engleză) (sau documentul echivalent pentru versiunea JVM-ului dumneavoastră).

Comentarii

  • Nu asta înseamnă dereferențiere. Nu înseamnă „a seta ultima referință a unui obiect la null”, ci mai degrabă a obține (citire) valoarea unei referințe, astfel încât să o puteți utiliza pentru operațiuni ulterioare. – user146043
  • Este try..finally încă o abordare validă și recomandată? Să presupunem că, anterior, am apelat o metodă nativă în finalize(), pot muta apelul în clauza finally? class Resource { finalize() { destroy(); } protected native void destroy(); } class Alt_Resource { try (Resource r = new Resource()) { // use r } finalize { r.destroy(); } –  > Por aashima.
  • r nu ar fi fost atribuit la blocul finally. Prin urmare, nu puteți apela destroy în acel moment. Acum, dacă ați corecta domeniul de aplicare pentru a avea crearea obiectului înainte de blocul try, ați ajunge la cazul urât „before try-with-resources”. –  > Por userAsh.
waku

Odată cu lansarea Java 1.7, aveți acum opțiunea suplimentară de a utiliza try-with-resources bloc. De exemplu,

public class Closeable implements AutoCloseable {
    @Override
    public void close() {
        System.out.println("closing..."); 
    }
    public static void main(String[] args) {
        try (Closeable c = new Closeable()) {
            System.out.println("trying..."); 
            throw new Exception("throwing..."); 
        }
        catch (Exception e) {
            System.out.println("catching..."); 
        }
        finally {
            System.out.println("finalizing..."); 
        } 
    }
}

Dacă executați această clasă, c.close() va fi executată atunci când se va executa try block este lăsat și înainte de catch și finally să fie executate. Spre deosebire de cazul clasei finalize() metodă, close() este garantată a fi executată. Cu toate acestea, nu este necesar să fie executată în mod explicit în cadrul secvenței finally clauză.

Comentarii

  • Ce se întâmplă dacă nu am folosit blocul try-with-resources? Cred că putem apela close în finalize() doar pentru a ne asigura că close a fost apelat. –  > Por shintoZ.
  • @shintoZ după cum am citit în răspunsurile de mai sus nu există nicio garanție de finalize() execuție –  > Por Asif Mushtaq.
Markus

Sunt pe deplin de acord cu alte răspunsuri, spunând să nu ne bazăm pe executarea finalizării.

În plus față de blocurile try-catch-finally, puteți utiliza Runtime#addShutdownHook (introdus în Java 1.3) pentru a efectua curățări finale în programul dvs.

Aceasta nu este același lucru cu destructori sunt, , dar se poate implementa un cârlig de închidere care să aibă obiecte de ascultare înregistrate pe care pot fi invocate metode de curățare (închiderea conexiunilor persistente la baze de date, eliminarea blocajelor de fișiere și așa mai departe) – lucruri pe care în mod normal, ar trebui să fie făcute în destructori.din nou – aceasta nu este un înlocuitor pentru destructori, dar, în unele cazuri, vă puteți apropia de funcționalitatea dorită cu ajutorul acesteia.

Avantajul acestui lucru este acela de a avea un comportament de deconstrucție cuplat în mod flexibil de restul programului dumneavoastră.

Comentarii

  • Se pare că addShutdownHook a fost introdus în Java 1.3. Oricum, este disponibil pentru mine în 1.5. 🙂 Vedeți asta: stackoverflow.com/questions/727151/… –  > Por skiphoppy.
  • FYI, din experiența mea, cârligele de închidere nu vor fi apelate dacă folosiți butonul roșu „terminate” în Eclipse – întregul JVM este distrus imediat, cârligele de închidere nu sunt apelate în mod grațios. Ceea ce înseamnă că este posibil să vedeți un comportament diferit în timpul dezvoltării și al producției dacă dezvoltați folosind eclipse –  > Por Hamy.
flicken

Nu, java.lang.Object#finalize este cea mai apropiată variantă pe care o puteți obține.

Cu toate acestea, când (și dacă) este apelat, nu este garantat.
A se vedea: java.lang.Runtime#runFinalizersOnExit(boolean)

Comentarii

  • O metodă care poate sau nu poate fi apelată este, în esență, inutilă din punctul meu de vedere. Ar fi fost mai bine să nu se polueze limbajul cu o metodă specială inutilă care, în cel mai bun caz, oferă un fals sentiment de siguranță. Nu voi înțelege niciodată de ce dezvoltatorii limbajului Java au crezut că finalize este o idee bună. –  > Por antred.
  • @antred Dezvoltatorii limbajului Java sunt de acord. Cred că, pe atunci, pentru unii dintre ei, a fost pentru prima dată când au proiectat un limbaj de programare și un mediu de execuție cu garbage collection. Ceea ce este mai puțin de înțeles, este de ce acel alt limbaj gestionat a copiat acest concept într-un moment în care se înțelegea deja că acest concept este o idee proastă. –  > Por Holger.
Steve Jessop

În primul rând, rețineți că, deoarece Java este un sistem de colectare a gunoiului, este rar să fie nevoie să faceți ceva cu privire la distrugerea obiectelor. În primul rând, pentru că, de obicei, nu aveți resurse gestionate de eliberat și, în al doilea rând, pentru că nu puteți prezice când sau dacă se va întâmpla, deci este inadecvat pentru lucruri care trebuie să se producă „imediat ce nimeni nu mai folosește obiectul meu”.

Puteți fi notificat după ce un obiect a fost distrus folosind java.lang.ref.PhantomReference (de fapt, a spune că a fost distrus ar putea fi puțin inexact, dar dacă o referință fantomă la el este pusă în coadă, atunci nu mai poate fi recuperat, ceea ce de obicei înseamnă același lucru). O utilizare obișnuită este:

  • separați resursa (resursele) din clasa dvs. care trebuie distruse într-un alt obiect ajutător (rețineți că, dacă tot ceea ce faceți este să închideți o conexiune, ceea ce este un caz obișnuit, nu trebuie să scrieți o clasă nouă: conexiunea care trebuie închisă ar fi „obiectul ajutător” în acest caz).
  • Atunci când creați obiectul principal, creați și o PhantomReference pentru acesta. Fie faceți ca aceasta să se refere la noul obiect ajutător, fie stabiliți o hartă de la obiectele PhantomReference la obiectele ajutătoare corespunzătoare.
  • După ce obiectul principal este colectat, PhantomReference este pus în coadă (sau mai degrabă poate fi pus în coadă – ca și în cazul finalizatorilor, nu există nicio garanție că va fi vreodată, de exemplu, dacă VM iese, atunci nu va aștepta). Asigurați-vă că îi procesați coada (fie într-un fir special, fie din când în când). Din cauza referinței hard la obiectul helper, obiectul helper nu a fost încă colectat. Deci, faceți orice curățare doriți pe obiectul de ajutor, apoi aruncați PhantomReference și, în cele din urmă, și obiectul de ajutor va fi colectat.

Există, de asemenea, finalize(), care arată ca un destructor, dar nu se comportă ca atare. De obicei, nu este o opțiune bună.

Comentarii

  • De ce o PhantomReference în loc de o WeakReference? –  > Por uckelman.
  • @uckelman: dacă tot ce doriți este o notificare, atunci PhantomReference își face treaba, cam pentru asta este conceput. Semantica suplimentară a lui WeakReference nu este necesară aici, iar în momentul în care ReferenceQueue este notificat, nu mai puteți recupera obiectul prin intermediul lui WeakReference, astfel încât singurul motiv pentru a-l utiliza este acela de a nu mai fi nevoit să vă amintiți că PhantomReference există. Orice muncă în plus pe care o face WeakReference este probabil neglijabilă, dar de ce să ne deranjăm cu ea? –  > Por Steve Jessop.
  • Vă mulțumim că ați făcut aluzie la PhantomReference. Nu este perfect, dar este totuși mai bine decât nimic. –  > Por foo.
  • @SteveJessop ce „muncă în plus”, credeți că are o referință slabă în comparație cu o referință fantomă? –  > Por Holger.
Shimi Bandiel

The finalize() este destructorul.

Cu toate acestea, nu ar trebui să fie utilizată în mod normal, deoarece este invocată după ce GC și nu se poate ști când se va întâmpla acest lucru (dacă se va întâmpla vreodată).

În plus, este nevoie de mai mult de un GC pentru a dezaloca obiectele care au finalize().

Ar trebui să încercați să faceți curățenie în locurile logice din codul dvs. folosind metoda try{...} finally{...} instrucțiuni!

Ravindra babu

Sunt de acord cu cele mai multe dintre răspunsuri.

Nu ar trebui să depindeți în totalitate nici de finalize sau ShutdownHook

finalizați

  1. JVM nu garantează când se va produce acest finalize() metodă va fi invocată.

  2. finalize() este apelat o singură dată de către firul GC. În cazul în care un obiect se reactivează din metoda de finalizare, atunci finalize nu va fi apelată din nou.

  3. În aplicația dumneavoastră, este posibil să aveți unele obiecte vii, pentru care colectarea gunoiului nu este niciodată invocată.

  4. Orice Exception care este aruncată de metoda de finalizare este ignorată de firul GC

  5. System.runFinalization(true) și Runtime.getRuntime().runFinalization(true) crește probabilitatea de a invoca metodele finalize() dar acum aceste două metode au fost eliminate. Aceste metode sunt foarte periculoase din cauza lipsei de siguranță a firelor de execuție și a posibilei creări de deadlock.

shutdownHooks

public void addShutdownHook(Thread hook)

Înregistrează un nou cârlig de închidere a mașinii virtuale.

Mașina virtuală Java se închide ca răspuns la două tipuri de evenimente:

  1. Programul iese în mod normal, atunci când ultimul fir de execuție care nu este un demon iese sau atunci când se execută funcția de ieșire (echivalent, System.exit) este invocată, sau

  2. Mașina virtuală se termină ca răspuns la o întrerupere a utilizatorului, cum ar fi tastarea ^C, sau la un eveniment la nivel de sistem, cum ar fi deconectarea utilizatorului sau oprirea sistemului.

  3. Un cârlig de închidere este pur și simplu un fir inițializat, dar care nu a fost inițiat. Atunci când mașina virtuală își începe secvența de închidere, aceasta va porni toate cârligele de închidere înregistrate într-o ordine nespecificată și le va lăsa să ruleze simultan. După ce toate cârligele s-au terminat, va rula toate finalizările neinvocate, dacă a fost activată finalizarea la ieșire.

  4. În cele din urmă, mașina virtuală se oprește. Rețineți că firele de execuție ale daemonilor vor continua să ruleze în timpul secvenței de închidere, la fel ca și firele non-daemon dacă închiderea a fost inițiată prin invocarea metodei exit.

  5. De asemenea, cârligele de închidere ar trebui să își încheie rapid activitatea. Atunci când un program invocă exit, se așteaptă ca mașina virtuală să se închidă și să iasă imediat.

    Dar chiar și documentația Oracle a citat că

În circumstanțe rare, mașina virtuală poate abera, adică se poate opri din funcționare fără a se închide în mod curat

Acest lucru se întâmplă atunci când mașina virtuală este terminată din exterior, de exemplu cu ajutorul funcției SIGKILL pe Unix sau cu ajutorul funcției TerminateProcess apel pe Microsoft Windows. Mașina virtuală poate, de asemenea, să întrerupă dacă o metodă nativă merge prost, de exemplu, prin coruperea structurilor de date interne sau prin încercarea de a accesa o memorie inexistentă. În cazul în care mașina virtuală avortează, nu se poate garanta dacă se va executa sau nu vreun cârlig de închidere.

Concluzie : utilizați try{} catch{} finally{} blocuri în mod corespunzător și eliberați resursele critice în finally(} bloc. În timpul eliberării resurselor în finally{} bloc, se prinde Exception și Throwable.

John Nilsson

Dacă vă îngrijorează doar memoria, nu o faceți. Aveți încredere în GC, face o treabă decentă. De fapt, am văzut ceva despre faptul că este atât de eficient încât ar putea fi mai bine pentru performanță să se creeze grămezi de obiecte mici decât să se utilizeze array-uri mari în unele cazuri.

DAU RĂSPUNSURI DE RAHAT

Poate că puteți folosi un bloc try … finally pentru a finaliza obiectul în fluxul de control la care utilizați obiectul. Bineînțeles că nu se întâmplă automat, dar nici distrugerea nu se face în C++. Deseori vedeți închiderea resurselor în blocul finally.

Comentarii

  • Acesta este răspunsul corect atunci când resursa în cauză are un singur proprietar și nu are niciodată referințe la ea „furate” de alt cod. –  > Por Steve Jessop.
Alexey

Există un @Cleanup în Lombok care seamănă în mare parte cu destructori C++:

@Cleanup
ResourceClass resource = new ResourceClass();

Când o procesează (în momentul compilării), Lombok inserează în mod corespunzător try-finally bloc astfel încât resource.close() este invocat, atunci când execuția părăsește domeniul de aplicare al variabilei. De asemenea, puteți specifica în mod explicit o altă metodă de eliberare a resursei, de ex. resource.dispose():

@Cleanup("dispose")
ResourceClass resource = new ResourceClass();

Comentarii

  • Avantajul pe care îl văd eu este că va exista mai puțină cuibărire (Ceea ce poate fi semnificativ dacă aveți o mulțime de obiecte care necesită „distrugere”). –  > Por Alexey.
  • Un bloc try-with-resource poate avea mai multe resurse dintr-o singură lovitură –  > Por Alexander.
  • Dar nu poate avea instrucțiuni între ele. –  > Por Alexey.
  • Corect. Presupun că atunci recomandarea este de a prefera try-with-resource, chiar și pentru mai multe resurse, cu excepția cazului în care este nevoie să existe instrucțiuni între ele care să te oblige să faci noi blocuri try-with-resource (creșterea gradului de cuibărit), atunci folosește @Cleanup –  > Por Alexander.
Nik

Cel mai apropiat echivalent al unui destructor în Java este finalize() metoda Marea diferență față de un destructor tradițional este că nu puteți fi siguri când va fi apelată, deoarece aceasta este responsabilitatea colectorului de gunoi. Vă recomand cu tărie să citiți cu atenție despre acest lucru înainte de a-l folosi, deoarece modelele RAIA tipice pentru mânerele de fișiere și așa mai departe nu vor funcționa în mod fiabil cu finalize().

mike rodent

Mă gândeam doar la întrebarea inițială… care, cred că putem concluziona din toate celelalte răspunsuri învățate și, de asemenea, din cele esențiale ale lui Bloch Effective Java, , punctul 7, „Evitați finalizatorii”, caută soluția la o întrebare legitimă într-o manieră nepotrivită pentru limbajul Java….:

… o soluție destul de evidentă pentru a face ceea ce dorește de fapt OP nu ar fi să păstrați toate obiectele care trebuie resetate într-un fel de „parc de joacă”, la care toate celelalte obiecte nerestabile să aibă referințe doar printr-un fel de obiect accesor…

Apoi, atunci când trebuie să „resetați”, deconectați țarcurile existente și faceți unul nou: toată rețeaua de obiecte din țarc este aruncată în derivă, pentru a nu se mai întoarce niciodată, urmând ca într-o zi să fie colectată de către CG.

În cazul în care oricare dintre aceste obiecte este Closeable (sau nu, dar au un close method), le puteți pune într-un Bag în playpen pe măsură ce sunt create (și eventual deschise), iar ultimul act al accesorului înainte de a tăia playpen-ul ar fi să treacă prin toate obiectele Closeables închiderea lor… ?

Codul ar arăta probabil cam așa:

accessor.getPlaypen().closeCloseables();
accessor.setPlaypen( new Playpen() );

closeCloseables ar fi probabil o metodă de blocare, probabil implicând un zăvorâtor (de ex. CountdownLatch), care să se ocupe de (și să aștepte după caz) orice Runnables/Callables în orice fire de execuție specifice pentru Playpen să se încheie în mod corespunzător, în special în firul JavaFX.

kaan

Multe răspunsuri excelente aici, dar există câteva informații suplimentare despre motivul pentru care ar trebui să evitați utilizarea finalize().

În cazul în care JVM iese din cauza System.exit() sau Runtime.getRuntime().exit(), , finalizatoarele nu vor fi executate în mod implicit. De la Javadoc pentru Runtime.exit():

Secvența de închidere a mașinii virtuale constă în două faze. În prima fază, toate cârligele de închidere înregistrate, dacă există, sunt pornite într-o ordine nespecificată și li se permite să ruleze concomitent până la terminarea lor. În cea de-a doua fază, toate finalizatoarele neinvocate sunt executate dacă a fost activată finalizarea la ieșire. Odată ce acest lucru s-a realizat, mașina virtuală se oprește.

Puteți apela System.runFinalization() dar acesta face doar „un efort maxim pentru a finaliza toate finalizările restante” – nu o garanție.

Există un System.runFinalizersOnExit() metodă, dar nu o folosiți – nu este sigură și este de mult timp depășită.

Dave

Dacă scrieți un Applet Java, puteți suprascrie metoda Applet „destroy()”. Aceasta este…

 * Called by the browser or applet viewer to inform
 * this applet that it is being reclaimed and that it should destroy
 * any resources that it has allocated. The stop() method
 * will always be called before destroy().

Evident, nu este ceea ce tu doriți, dar s-ar putea să fie ceea ce caută alte persoane.

tyler

Deși au existat progrese considerabile în tehnologia GC din Java, trebuie să fiți atenți la referințe. Îmi vin în minte numeroase cazuri de modele de referință aparent banale care sunt de fapt cuiburi de șobolani sub capotă.

Din mesajul tău nu pare că încerci să implementezi o metodă de resetare în scopul reutilizării obiectelor (adevărat?). Obiectele dvs. dețin orice alt tip de resurse care trebuie curățate (de exemplu, fluxuri care trebuie închise, orice obiecte împrumutate sau împrumutate care trebuie returnate)? Dacă singurul lucru care vă îngrijorează este dezalocarea memoriei, atunci aș reconsidera structura obiectelor mele și aș încerca să verific dacă obiectele mele sunt structuri autonome care vor fi curățate în momentul GC.

Anubhav Mishra

Nu, Java nu are nici un destructori .Principalul motiv din spatele acestui lucru în Java este Garbage Collectors care lucrează pasiv în fundal întotdeauna și toate obiectele sunt făcute în memoria heap, care este locul unde funcționează GC .În c++ trebuie să apelăm în mod explicit funcția de ștergere, deoarece nu există un astfel de Garbage collector.

Ayesha

În Java, garbage collector șterge automat obiectele neutilizate pentru a elibera memoria. Prin urmare, Java nu dispune de destructori.

Manas

În Java nu există o clasă cu destructor exact, clasa este distrusă automat de către garbage collector, dar puteți face acest lucru cu ajutorul clasei de mai jos, dar nu este exact același lucru:

finalize()

A existat o întrebare care a generat o discuție aprofundată despre finalize , astfel încât ar trebui să obțineți mai multă profunzime dacă este necesar…

ChristianGLong

Obișnuiam să mă ocup în principal de C++ și asta m-a condus și pe mine la căutarea unui destructor. Acum folosesc foarte mult JAVA. Ceea ce am făcut eu, și poate nu este cel mai bun caz pentru toată lumea, dar am implementat propriul meu destructor prin resetarea tuturor valorilor fie la 0, fie acolo implicit, printr-o funcție.

Exemplu:

public myDestructor() {

variableA = 0; //INT
variableB = 0.0; //DOUBLE & FLOAT
variableC = "NO NAME ENTERED"; //TEXT & STRING
variableD = false; //BOOL

}

În mod ideal, acest lucru nu va funcționa în toate situațiile, dar în cazul în care există variabile globale, va funcționa atâta timp cât nu aveți o mulțime de variabile.

Știu că nu sunt cel mai bun programator Java, dar pentru mine pare să funcționeze.

Comentarii

  • Încercați să folosiți mai mult obiectele imuabile, după ce „înțelegeți”, totul va avea mai mult sens 🙂 –  > Por R. van Twisk.
  • Acest lucru nu este atât de greșit, cât este lipsit de sens – adică nu realizează nimic. Dacă programul dvs. necesită ca tipurile brute să fie resetate pentru a funcționa corect, atunci instanțele claselor dvs. sunt încadrate incorect, ceea ce înseamnă că, probabil, realocați proprietățile unui obiect existent la proprietățile unui nou obiect, fără a crea un nou Obiect(). –  > Por simo.3792.
  • Doar că există o mulțime de nevoi de resetare a variabilelor. Am ales numele de destructor pentru că se potrivește cu ceea ce fac. Realizează ceva, doar că nimic pe înțelesul dumneavoastră -.  > Por ChristianGLong.