Hej!

Jeg tror ikke, du vil blive alt for overrasket, hvis jeg fortæller dig, at din computer har en begrænset mængde hukommelse :) Selv en harddisk - generelt mange gange større end RAM-lagerplads - kan pakkes til kapacitet med dine yndlingsspil, tv-shows, og mere. For at forhindre dette i at ske, skal du overvåge den aktuelle hukommelsestilstand og slette unødvendige filer fra din computer. Hvad har Java-programmering med alt dette at gøre? Alt! Når alt kommer til alt, når Java-maskinen opretter ethvert objekt, allokerer den hukommelse til det pågældende objekt.

I et rigtigt stort program skabes titusinder og hundredtusindvis af objekter, og hver af dem har sit eget stykke hukommelse tildelt til det. Men hvor længe tror du, at alle disse objekter eksisterer? Lever de hele tiden vores program kører? Selvfølgelig ikke. Selv med alle fordelene ved Java-objekter, er de ikke udødelige :) Objekter har deres egen livscyklus. I dag tager vi en lille pause fra at skrive kode og ser på denne proces :) Desuden er det meget vigtigt for din forståelse af, hvordan et program fungerer, og hvordan ressourcer styres. Så hvornår begynder et objekts liv? Som en person - fra dens fødsel, det vil sige skabelsen.


Cat cat = new Cat(); // Here the lifecycle of our Cat object begins!

Først tildeler Java Virtual Machine den nødvendige mængde hukommelse til at skabe objektet. Så opretter det en reference til denne hukommelse. I vores tilfælde hedder den reference cat, så vi kan holde styr på den. Derefter initialiseres alle dens variable, konstruktøren kaldes, og - ta-da! — vores nyslåede genstand lever sit eget liv :)

Objekternes levetid varierer, så vi kan ikke give nøjagtige tal her. Under alle omstændigheder lever den i nogen tid inde i programmet og udfører sine funktioner. For at være præcis er et objekt "levende", så længe der er referencer til det. Så snart der ikke er nogen referencer tilbage, "dør" objektet. Eksempel:


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;

   }

}

Lamborghini Diablo-bilobjektet holder op med at være i live på anden linje i metoden main(). Der var kun én reference til den, og så blev den reference sat lig med null. Da der ikke er nogen tilbageværende referencer til Lamborghini Diablo, bliver den tildelte hukommelse "skrald". En reference behøver ikke at være sat til null for at dette kan ske:


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

}

Her oprettede vi et andet objekt og tildelte derefter dette nye objekt til referencen lamborghini. Nu Lamborghini Gallardohar objektet to referencer, men Lamborghini Diabloobjektet har ingen. Det betyder, at Diabloobjektet nu er skrald. Det er her, Javas indbyggede mekanisme kaldet garbage collector (GC) kommer i spil.

Skraldesamleren er en intern Java-mekanisme, der er ansvarlig for at frigøre hukommelse, dvs. fjerne unødvendige genstande fra hukommelsen. Der er en god grund til, at vi her har valgt et billede af en robotstøvsuger. Når alt kommer til alt, fungerer skraldesamleren stort set på samme måde: I baggrunden "rejser" den rundt i dit program og samler affald praktisk talt uden anstrengelse fra din side. Dens opgave er at fjerne objekter, der ikke længere bruges i programmet.

Hvis du gør dette, frigøres hukommelse i computeren til andre objekter. Kan du huske, at vi i begyndelsen af ​​lektionen sagde, at du i det almindelige liv skal overvåge din computers tilstand og slette unødvendige filer? Nå, i tilfælde af Java-objekter, gør affaldssamleren dette for dig. Skraldesamleren kører gentagne gange, mens dit program kører: du behøver ikke udtrykkeligt at kalde det eller give det kommandoer, selvom dette er teknisk muligt. Senere vil vi tale mere om det og analysere dets arbejde mere detaljeret.

Når skraldesamleren når frem til en genstand, lige før den ødelægger genstanden, kalder den en speciel metode — finalize()— på genstanden. Denne metode kan frigive andre ressourcer, der bruges af objektet. Metoden finalize()er en del af Objectklassen. Det betyder, at ud over de equals(), hashCode()og toString()metoder, du mødte tidligere, har hvert objekt denne metode. Den adskiller sig fra andre metoder ved, at den er - hvordan skal jeg sige det - meget lunefuld.

Især kaldes det ikke altid før ødelæggelsen af ​​et objekt. Programmering er en præcis bestræbelse. Programmøren fortæller computeren at gøre noget, og computeren gør det. Jeg formoder, at du allerede er vant til denne adfærd, så i starten kan det være svært for dig at acceptere følgende idé: "Før destruktion af objekter, kaldes klassens finalize()metode . Eller måske kaldes den ikke. Det hele afhænger af Objectdit held!"

Alligevel er det sandt. Java-maskinen bestemmer selv, om finalize()metoden skal kaldes fra sag til sag. Lad os for eksempel prøve at køre følgende kode som et eksperiment:


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; // This is when the first object becomes available to the garbage collector
       }
   }

   @Override
   protected void finalize() throws Throwable {
       System.out.println("Cat object destroyed!");
   }
}

Vi opretter et Catobjekt, og i den næste kodelinje sætter vi dets eneste reference lig med null. Og det gør vi en million gange. Vi tilsidesatte eksplicit finalize()metoden, så den udskriver en streng til konsollen en million gange (en gang for hver gang, den ødelægger et Catobjekt). Men nej! For at være præcis kørte den kun 37.346 gange på min computer! Det vil sige, at kun én gang ud af 27 gange besluttede den Java-maskine, der var installeret på min maskine, at kalde finalize()metoden.

I andre tilfælde skete affaldsindsamling uden. Prøv at køre denne kode for dig selv: højst sandsynligt vil du få et andet resultat. Som du kan se, finalize()kan næppe kaldes en pålidelig partner :) Så et lille råd til fremtiden: stol ikke på metoden finalize()til at frigøre kritiske ressourcer. Måske vil JVM kalde det, eller måske ikke. Hvem ved?

Hvis, mens dit objekt er i live, rummer det nogle ressourcer, der er super vigtige for ydeevnen, for eksempel en åben databaseforbindelse, er det bedre at oprette en speciel metode i din klasse til at frigive dem og derefter kalde det eksplicit, når objektet ikke længere er havde brug for. På den måde ved du med sikkerhed, at dit programs ydeevne ikke vil lide skade. Fra starten sagde vi, at det er meget vigtigt at arbejde med hukommelse og fjerne skrald, og det er sandt. Forkert håndtering af ressourcer og misforståelse af, hvordan unødvendige genstande bliver ryddet op, kan føre til hukommelseslækager. Dette er en af ​​de mest kendte programmeringsfejl.

Hvis programmører skriver deres kode forkert, kan der blive tildelt ny hukommelse til nyoprettede objekter hver gang, mens gamle, unødvendige objekter muligvis ikke er tilgængelige for fjernelse af skraldeopsamleren. Da vi lavede en analogi med en robotstøvsuger, så forestil dig, hvad der ville ske, hvis du, inden du starter robotten, spreder sokker rundt i huset, knækker en glasvase og efterlader en Lego-byggeklodser over hele gulvet. Robotten vil selvfølgelig forsøge at gøre sit arbejde, men på et tidspunkt vil den sætte sig fast.

For at lade robotstøvsugeren fungere korrekt, skal du holde gulvet i god stand og fjerne alt, som robotten ikke kan håndtere. Samme princip gælder for Javas skraldemand. Hvis der er mange genstande tilbage i et program, som ikke kan ryddes op (som en sok eller Lego byggeklods til vores robotstøvsuger), vil du på et tidspunkt løbe tør for hukommelse. Og det er måske ikke kun dit program, der fryser - alle andre programmer, der kører på computeren, kan blive påvirket. De har måske heller ikke nok hukommelse.

Du behøver ikke at huske dette. Du skal bare forstå princippet bag, hvordan det fungerer.