logo

Zarządzanie pamięcią w Javie

W Javie zarządzanie pamięcią to proces alokacji i dealokacji obiektów, zwany zarządzaniem pamięcią. Java automatycznie zarządza pamięcią. Java korzysta z automatycznego systemu zarządzania pamięcią zwanego a Śmieciarz . Dlatego nie jesteśmy zobowiązani do implementowania logiki zarządzania pamięcią w naszej aplikacji. Zarządzanie pamięcią Java dzieli się na dwie główne części:

    Struktura pamięci JVM Praca zbieracza śmieci

Struktura pamięci JVM

JVM tworzy różne obszary danych wykonawczych na stercie. Obszary te są wykorzystywane podczas wykonywania programu. Obszary pamięci są niszczone po wyjściu JVM, natomiast obszary danych są niszczone po wyjściu wątku.

Zarządzanie pamięcią w Javie

Obszar metody

Obszar metody jest częścią pamięci sterty współdzielonej pomiędzy wszystkimi wątkami. Tworzy się podczas uruchamiania JVM. Służy do przechowywania struktury klasy, nazwy nadklasy, nazwy interfejsu i konstruktorów. JVM przechowuje następujące rodzaje informacji w obszarze metody:

Niezbędna kompilacja Ubuntu
  • W pełni kwalifikowana nazwa typu (np. String)
  • Modyfikatory typu
  • Bezpośrednia nazwa nadklasy typu
  • Ustrukturyzowana lista w pełni kwalifikowanych nazw superinterfejsów.

Obszar sterty

Heap przechowuje rzeczywiste obiekty. Tworzy się podczas uruchamiania JVM. W razie potrzeby użytkownik może kontrolować stertę. Może mieć stały lub dynamiczny rozmiar. Kiedy używasz nowego słowa kluczowego, JVM tworzy instancję obiektu na stercie. Podczas gdy odniesienie do tego obiektu jest przechowywane na stosie. Dla każdego działającego procesu JVM istnieje tylko jedna sterta. Gdy sterta się zapełni, śmieci są zbierane. Na przykład:

 StringBuilder sb= new StringBuilder(); 

Powyższa instrukcja tworzy obiekt klasy StringBuilder. Obiekt przydzielany jest do sterty, a referencja sb do stosu. Kopiec jest podzielony na następujące części:

  • Młoda generacjA
  • Przestrzeń ocalałego
  • Stare pokolenie
  • Trwałe pokolenie
  • Pamięć podręczna kodu

Typ odniesienia

Istnieją cztery typy referencji: Mocny , Słaby , Miękki , I Odniesienie fantomowe . Różnica między typami odniesień polega na tym, że obiekty na stercie, do których się odnoszą, kwalifikują się do zbierania elementów bezużytecznych na podstawie różnych kryteriów.

Silne odniesienie: Jest to bardzo proste, ponieważ używamy go w naszym codziennym programowaniu. Żaden obiekt, do którego przypisano silne odniesienie, nie kwalifikuje się do usuwania elementów bezużytecznych. Silne odniesienie możemy stworzyć za pomocą następującego stwierdzenia:

 StringBuilder sb= new StringBuilder(); 

Słabe odniesienie: Nie przetrwa po kolejnym procesie zbierania śmieci. Jeżeli nie jesteśmy pewni, kiedy ponownie poprosimy o podanie danych. W tym stanie możemy stworzyć do niego słabe odniesienie. W przypadku, gdy moduł zbierający elementy bezużyteczne przetworzy obiekt, zniszczy go. Kiedy ponownie spróbujemy odzyskać ten obiekt, otrzymamy wartość null. Jest zdefiniowany w java.lang.ref.Słabe odniesienie klasa. Możemy stworzyć słabe odniesienie, używając następującej instrukcji:

 WeakReference reference = new WeakReference(new StringBuilder()); 

Miękkie odniesienie: Są zbierane, gdy w aplikacji zaczyna brakować pamięci. Odśmiecacz nie zbiera obiektów, do których można łatwo dotrzeć. Wszystkie obiekty, do których istnieją miękkie odniesienia, są zbierane przed zgłoszeniem błędu OutOfMemoryError. Możemy utworzyć miękkie odniesienie, używając następującej instrukcji:

 SoftReference reference = new SoftReference(new StringBuilder()); 

Odniesienie do fantomu: Jest dostępny w Java.lang.ref pakiet. Jest zdefiniowany w java.lang.ref.PhantomReference klasa. Obiekt, który ma jedynie pozorne odniesienie wskazujące je, może zostać zebrany, gdy moduł zbierający elementy bezużyteczne chce to zebrać. Możemy utworzyć odniesienie fantomowe, używając następującej instrukcji:

 PhantomReference reference = new PhantomReference(new StringBuilder()); 

Obszar stosu

Obszar stosu jest generowany podczas tworzenia wątku. Może mieć rozmiar stały lub dynamiczny. Pamięć stosu jest przydzielana na wątek. Służy do przechowywania danych i wyników cząstkowych. Zawiera odniesienia do obiektów sterty. Przechowuje także samą wartość, a nie odniesienie do obiektu ze sterty. Zmienne przechowywane na stosie mają określoną widoczność, zwaną zakresem.

Rama stosu: Ramka stosu to struktura danych zawierająca dane wątku. Dane wątku reprezentują stan wątku w bieżącej metodzie.

  • Służy do przechowywania częściowych wyników i danych. Wykonuje również dynamiczne łączenie, zwracanie wartości metodami i wysyłanie wyjątków.
  • Po wywołaniu metody tworzona jest nowa ramka. Niszczy ramkę po zakończeniu wywołania metody.
  • Każda ramka zawiera własną tablicę zmiennych lokalnych (LVA), stos argumentów (OS) i dane ramki (FD).
  • Rozmiary LVA, OS i FD określane w czasie kompilacji.
  • W dowolnym momencie danego wątku sterowania aktywna jest tylko jedna ramka (ramka wykonania metody). Ramka ta nazywana jest ramką bieżącą, a jej metoda nazywana jest metodą bieżącą. Klasa metody nazywana jest klasą bieżącą.
  • Ramka zatrzymuje bieżącą metodę, jeśli jej metoda wywołuje inną metodę lub jeśli metoda zakończy się.
  • Ramka utworzona przez wątek jest lokalna dla tego wątku i żaden inny wątek nie może się do niej odwoływać.

Stos metod natywnych

Nazywa się go również stosem C. Jest to stos kodu natywnego napisanego w języku innym niż Java. Java Native Interface (JNI) wywołuje natywny stos. Wydajność natywnego stosu zależy od systemu operacyjnego.

jakie miesiące są q1

Rejestry komputerów

Z każdym wątkiem jest powiązany rejestr licznika programów (PC). Rejestr komputera przechowuje adres zwrotny lub natywny wskaźnik. Zawiera także adres aktualnie wykonywanych instrukcji JVM.

Praca zbieracza śmieci

Przegląd zbieracza śmieci

Kiedy program jest wykonywany w Javie, wykorzystuje pamięć na różne sposoby. Sterta jest częścią pamięci, w której żyją obiekty. To jedyna część pamięci zaangażowana w proces usuwania śmieci. Nazywa się go również stertą śmieci. Całe wyrzucanie elementów bezużytecznych dba o to, aby sterta miała jak najwięcej wolnego miejsca. Zadaniem modułu zbierającego elementy bezużyteczne jest odnajdywanie i usuwanie obiektów, do których nie można dotrzeć.

Alokacja obiektu

Podczas alokacji obiektu JVM JRockit sprawdza rozmiar obiektu. Rozróżnia małe i duże obiekty. Mały i duży rozmiar zależy od wersji JVM, rozmiaru sterty, strategii usuwania elementów bezużytecznych i używanej platformy. Rozmiar obiektu wynosi zwykle od 2 do 128 KB.

Małe obiekty są przechowywane w obszarze lokalnym wątku (TLA), który jest wolnym fragmentem sterty. TLA nie synchronizuje się z innymi wątkami. Kiedy TLA się zapełni, żąda nowego TLA.

Z drugiej strony duże obiekty, które nie mieszczą się w TLA, są bezpośrednio przydzielane do sterty. Jeśli wątek korzysta z młodej przestrzeni, jest przechowywany bezpośrednio w starej przestrzeni. Duży obiekt wymaga większej synchronizacji między wątkami.

Co robi moduł zbierający śmieci Java?

JVM kontroluje moduł zbierający elementy bezużyteczne. JVM decyduje, kiedy wykonać zbieranie śmieci. Możemy również poprosić maszynę JVM o uruchomienie modułu zbierającego elementy bezużyteczne. Jednak pod żadnym pozorem nie ma gwarancji, że maszyna JVM będzie spełniać wymagania. JVM uruchamia moduł zbierający elementy bezużyteczne, jeśli wykryje, że kończy się pamięć. Gdy program Java wysyła żądanie do modułu zbierającego elementy bezużyteczne, maszyna JVM zwykle szybko spełnia żądanie. Nie gwarantuje, że prośby zostaną przyjęte.

Należy zrozumieć, że „ kiedy obiekt kwalifikuje się do odśmiecania? '

Każdy program Java ma więcej niż jeden wątek. Każdy wątek ma swój stos wykonawczy. W programie Java istnieje wątek do uruchomienia, który jest metodą main(). Teraz możemy powiedzieć, że obiekt kwalifikuje się do odśmiecania, gdy żaden aktywny wątek nie ma do niego dostępu. Moduł zbierający elementy bezużyteczne uważa ten obiekt za kwalifikujący się do usunięcia. Jeśli program ma zmienną referencyjną odnoszącą się do obiektu, zmienną referencyjną dostępną dla aktywnego wątku, obiekt ten jest wywoływany osiągalny .

Tutaj pojawia się pytanie, że „ Czy aplikacji Java może zabraknąć pamięci? '

Odpowiedź brzmi tak. System zbierania elementów bezużytecznych próbuje usunąć obiekty z pamięci, gdy nie są one używane. Jeśli jednak utrzymujesz wiele aktywnych obiektów, odśmiecanie nie gwarantuje, że jest wystarczająca ilość pamięci. Skutecznie zarządzana będzie tylko dostępna pamięć.

Rodzaje zbierania śmieci

Wyróżnia się pięć rodzajów zbierania śmieci:

Oracle SQL nie jest równy
    Seryjny GC:Wykorzystuje podejście „znacz i zamiataj” w przypadku młodych i starszych pokoleń, co jest mniejszą i większą GC.Równoległe GC:Jest podobny do serial GC, z tą różnicą, że tworzy N (liczbę rdzeni procesora w systemie) wątków w celu usuwania śmieci nowej generacji.Równoległy stary GC:Jest podobny do równoległego GC, z tą różnicą, że wykorzystuje wiele wątków dla obu generacji.Moduł zbierający współbieżne skanowanie znaczników (CMS):Zajmuje się zbieraniem śmieci dla starego pokolenia. Możesz ograniczyć liczbę wątków w kolektorze CMS za pomocą XX:ParalleCMSThreads=opcja JVM . Jest również znany jako moduł zbierający współbieżne niskie pauzy.Odbieracz śmieci G1:Został wprowadzony w Javie 7. Jego celem jest zastąpienie kolektora CMS. Jest to kolektor równoległy, współbieżny i CMS. Nie ma przestrzeni młodego i starego pokolenia. Dzieli stertę na kilka kopców o jednakowej wielkości. Najpierw gromadzi regiony z mniejszą liczbą aktualnych danych.

Algorytm zaznaczania i przeczesywania

JRockit JVM używa algorytmu zaznaczania i zamiatania do usuwania elementów bezużytecznych. Zawiera dwie fazy, fazę znakowania i fazę przemiatania.

Oznacz fazę: Obiekty dostępne z wątków, uchwytów natywnych i innych źródeł głównych GC są oznaczone jako aktywne. Każde drzewo obiektów ma więcej niż jeden obiekt główny. Katalog główny GC jest zawsze osiągalny. Zatem każdy obiekt, który ma w swoim katalogu głównym element zbierający elementy bezużyteczne. Identyfikuje i oznacza wszystkie przedmioty, które są w użyciu, a pozostałe można uznać za śmieci.

Zarządzanie pamięcią w Javie

Faza przemiatania: W tej fazie sterta jest przemierzana w celu znalezienia luki pomiędzy żywymi obiektami. Luki te są rejestrowane na wolnej liście i są dostępne dla nowego przydziału obiektów.

Istnieją dwie ulepszone wersje narzędzia Mark and Sweep:

    Równoczesne zaznaczanie i zamiatanie Zaznaczanie równoległe i przeciąganie

Równoczesne zaznaczanie i zamiatanie

Umożliwia to dalsze działanie wątków podczas dużej części wyrzucania elementów bezużytecznych. Wyróżnia się następujące rodzaje oznakowania:

    Oznaczenie wstępne:Identyfikuje zbiór główny żywych obiektów. Odbywa się to podczas wstrzymania wątków.Równoczesne oznakowanie:W tym oznaczeniu przestrzegane są odniesienia z zestawu głównego. Znajduje i zaznacza resztę żywych obiektów na stercie. Odbywa się to podczas działania wątku.Oznaczenie wstępnego czyszczenia:Identyfikuje zmiany dokonane poprzez jednoczesne zaznaczanie. Oznaczono i znaleziono inne żywe obiekty. Odbywa się to podczas działania wątków.Ostateczne oznaczenie:Identyfikuje zmiany dokonane poprzez oznaczenie wstępnego czyszczenia. Oznaczono i znaleziono inne żywe obiekty. Odbywa się to podczas wstrzymania wątków.

Zaznaczanie równoległe i przeciąganie

Wykorzystuje cały dostępny procesor w systemie, aby jak najszybciej pozbyć się śmieci. Nazywa się go również równoległym modułem zbierającym śmieci. Wątki nie są wykonywane, gdy wykonywane jest równoległe wyrzucanie elementów bezużytecznych.

Plusy Mark i Sweep

  • Jest to proces powtarzający się.
  • Jest to nieskończona pętla.
  • Podczas wykonywania algorytmu nie są dozwolone żadne dodatkowe koszty ogólne.

Wady Marka i Sweepa

  • Zatrzymuje normalne wykonywanie programu na czas działania algorytmu zbierania śmieci.
  • Działa wiele razy w programie.