Zarządzanie pamięcią w Java

Co to jest pamięć stosu?

Stos w Javie to sekcja pamięci zawierająca metody, zmienne lokalne i zmienne referencyjne. Do pamięci stosu odwołuje się zawsze w kolejności „ostatni na wejściu, pierwszy na wyjściu”. Zmienne lokalne są tworzone na stosie.

Co to jest pamięć sterty?

Sterta to sekcja pamięci, która zawiera obiekty i może również zawierać zmienne referencyjne. Zmienne instancji są tworzone w stercie.

Alokacja pamięci w Java

Alokacja pamięci w Java to proces, podczas którego sekcje pamięci wirtualnej są rezerwowane w programie do przechowywania zmiennych oraz instancji struktur i klas. Jednak podczas deklaracji pamięć nie jest przydzielana obiektowi, a jedynie tworzone jest odwołanie. Do alokacji pamięci obiektu używana jest metoda new(), dzięki czemu obiektowi zawsze przydzielana jest pamięć na stercie.

Java Alokacja pamięci podzielona jest na następujące sekcje:

  1. kupa
  2. Stos
  3. Code
  4. Statyczny

Taki podział pamięci jest niezbędny do jej efektywnego zarządzania.

  • kod sekcja zawiera Twoje kod bajtowy.
  • Stos zawiera część pamięci metody, zmienne lokalne i zmienne referencyjne.
  • kupa sekcja zawiera Obiekty (może również zawierać zmienne referencyjne).
  • Statyczny sekcja zawiera Dane/metody statyczne.

Różnica między zmienną lokalną a zmienną instancji

Zmienna instancji jest zadeklarowane wewnątrz klasy, ale nie wewnątrz metody

class Student{ 
int num; // num is  instance variable 
public void showData{}

Zmienna lokalna są zadeklarowane wewnątrz a metoda m.in metoda argumenty.

public void sum(int a){

int x = int a +  3;

// a , x are local variables;

}

Różnica między stosem a stertą

Kliknij tutaj jeśli film nie jest dostępny

Weźmy przykład, aby lepiej to zrozumieć. Rozważmy, że Twoja metoda główna wywołuje metodę m1

public void m1{
int x=20
}

Na stosie Java ramka zostanie utworzona metodą m1.

Java Stos i stos

Zmienna X w m1 zostanie również utworzona w ramce dla m1 na stosie. (Patrz obrazek poniżej).

Java Stos i stos

Metoda m1 wywołuje metodę m2. Na stosie Java tworzona jest nowa ramka dla m2 na górze ramki m1.

Java Stos i stos

Java Stos i stos

Zmienne b i c zostaną również utworzone w ramce m2 na stosie.

public void m2(int b){
boolean c;
}

Java Stos i stos

Ta sama metoda m2 wywołuje metodę m3. Ponownie ramka m3 jest tworzona na szczycie stosu (patrz poniższy obrazek).

Java Stos i stos

Java Stos i stos

Załóżmy teraz, że nasza metoda m3 tworzy obiekt dla klasy „Konto”, która ma dwa zmienna instancji int p i int q.

Account {
             Int p;
             Int q;
       }

Oto kod metody m3

public void m3(){
	Account ref = new Account();
	// more code
}

Instrukcja new Account() utworzy obiekt konta na stercie.

Java Stos i stos

Zmienna referencyjna „ref” zostanie utworzona na stosie Java.

Java Stos i stos

Operator przypisania „=” utworzy zmienną referencyjną wskazującą na obiekt w stercie.

Java Stos i stos

Gdy metoda zakończy swoje wykonywanie, przepływ sterowania powróci do metody wywołującej. W tym przypadku jest to metoda m2.

Java Stos i stos

Stos z metody m3 zostanie wypłukany.

Java Stos i stos

Ponieważ zmienna referencyjna nie będzie już wskazywała obiektu na stercie, kwalifikowałaby się do odśmiecania.

Java Stos i stos

Gdy metoda m2 zakończy swoje wykonywanie, zostanie ona wyjęta ze stosu, a wszystkie jej zmienne zostaną opróżnione i nie będą już dostępne do użycia.

Podobnie jest w przypadku metody m1.

Ostatecznie przepływ sterowania powróci do punktu początkowego programu. Który zwykle jest metodą „główną”.

Co się stanie, jeśli obiekt ma referencję jako zmienną instancji?

public static void main(String args[]) {
  A parent = new A(); //more code } class A{ B child = new B(); int e; //more code } class B{ int c; int d;  //more code }

W tym przypadku zmienna referencyjna „child” zostanie utworzona w stercie, która z kolei będzie wskazywała na jej obiekt, jak na poniższym schemacie.

Java Stos i stos

Na czym polega zbieranie śmieci Java?

Zbiórka śmieci w Java to proces, dzięki któremu programy automatycznie zarządzają pamięcią. Garbage Collector (GC) znajduje nieużywane obiekty i usuwa je, aby odzyskać pamięć. W Java, dynamiczna alokacja pamięci dla obiektów jest realizowana za pomocą operatora new, który wykorzystuje część pamięci, a pamięć pozostaje przydzielona do momentu, aż pojawią się odwołania do wykorzystania obiektu.

Gdy nie ma żadnych odniesień do obiektu, przyjmuje się, że nie jest on już potrzebny i pamięć zajmowaną przez obiekt można odzyskać. Nie ma wyraźnej potrzeby niszczenia obiektu jako Java automatycznie obsługuje dealokację.

Technika, która pozwala to osiągnąć, nazywa się Zbieranie śmieci. Programy, które nie zwalniają pamięci, mogą w końcu ulec awarii, gdy w systemie zabraknie pamięci do przydzielenia. Mówi się, że te programy mają wycieki pamięci. Zbiórka śmieci w Java dzieje się automatycznie w trakcie istnienia programu, eliminując potrzebę cofania alokacji pamięci i zapobiegając w ten sposób wyciekom pamięci.

W języku C obowiązkiem programisty jest zwolnienie alokacji pamięci przydzielanej dynamicznie za pomocą funkcji free(). To jest gdzie Java prowadzi do zarządzania pamięcią.

Uwaga: Wszystkie obiekty są tworzone w sekcji Heap pamięci. Więcej na ten temat w późniejszym samouczku.

Przykład: Aby nauczyć się mechanizmu zbierania śmieci w Java

Krok 1) Skopiuj poniższy kod do edytora.

class Student{
int a;
int b;
  public void setData(int c,int d){
    a=c;
    b=d;
  }
  public void showData(){
    System.out.println("Value of a = "+a);
    System.out.println("Value of b = "+b);
  }
  public static void main(String args[]){
    Student s1 = new Student();
    Student s2 = new Student();
    s1.setData(1,2);
    s2.setData(3,4);
    s1.showData();
    s2.showData();
    //Student s3;
    //s3=s2;
    //s3.showData();
    //s2=null;
    //s3.showData();
    //s3=null;
    //s3.showData();
  }
}

Krok 2) Zapisz, skompiluj i uruchom kod. Jak pokazano na schemacie, tworzone są dwa obiekty i dwie zmienne referencyjne.


Mechanizm zbierający śmieci

Krok 3) Odkomentuj wiersz nr 20,21,22. Zapisz, skompiluj i uruchom kod.

Krok 4) Jak pokazano na poniższym diagramie, dwie zmienne referencyjne wskazują na ten sam obiekt.

Mechanizm zbierający śmieci

Krok 5) Odkomentuj wiersze nr 23 i 24. Skompiluj, zapisz i uruchom kod

Krok 6) Jak pokazano na poniższym diagramie, s2 przyjmuje wartość null, ale s3 nadal wskazuje na obiekt i nie kwalifikuje się do usuwania elementów bezużytecznych Java.

Mechanizm zbierający śmieci

Krok 7) Odkomentuj wiersze nr 25 i 26. Zapisz, skompiluj i uruchom kod

Krok 8) W tym momencie nie ma żadnych odniesień wskazujących na obiekt i kwalifikuje się do odśmiecania. Zostanie usunięty z pamięci i nie będzie możliwości jego odzyskania.

Naucz się zbierać śmieci

Jak usunąć obiekt w Java?

1) Jeśli chcesz, aby Twój obiekt kwalifikował się do zbierania śmieci, przypisz jego zmienną referencyjną wartość null.

2) Typy pierwotne nie są obiektami. Nie można im przypisać wartości null.

Jak usunąć obiekt w Java

Podsumowując:

  • Po wywołaniu metody na szczycie stosu tworzona jest ramka.
  • Po zakończeniu wykonywania metody przepływ kontroli powraca do metody wywołującej, a odpowiadająca jej ramka stosu jest opróżniana.
  • Zmienne lokalne są tworzone na stosie
  • Zmienne instancji są tworzone na stercie i są częścią obiektu, do którego należą.
  • Zmienne referencyjne są tworzone na stosie.