CodeGym/Kursy Java/Moduł 3/Pamięć w JVM

Pamięć w JVM

Dostępny

Zrozumienie pamięci w JVM

Jak już wiesz, JVM uruchamia w sobie programy Java. Jak każda maszyna wirtualna posiada własny system organizacji pamięci.

Układ pamięci wewnętrznej wskazuje sposób działania aplikacji Java. W ten sposób można zidentyfikować wąskie gardła w działaniu aplikacji i algorytmów. Zobaczmy, jak to działa.

Zrozumienie pamięci w JVM

Ważny! Oryginalny model Java nie był wystarczająco dobry, więc został poprawiony w Javie 1.5. Ta wersja jest używana do dziś (Java 14+).

Stos wątków

Model pamięci Java używany wewnętrznie przez JVM dzieli pamięć na stosy wątków i sterty. Spójrzmy na model pamięci Java, logicznie podzielony na bloki:

Stos wątków

Wszystkie wątki uruchomione w JVM mają swój własny stos . Stos z kolei przechowuje informacje o tym, jakie metody wywołał wątek. Nazwę to „stosem wywołań”. Stos wywołań jest wznawiany, gdy tylko wątek wykona swój kod.

Stos wątku zawiera wszystkie zmienne lokalne wymagane do wykonywania metod na stosie wątku. Wątek może uzyskać dostęp tylko do własnego stosu. Zmienne lokalne nie są widoczne dla innych wątków, tylko dla wątku, który je utworzył. W sytuacji, gdy dwa wątki wykonują ten sam kod, oba tworzą własne zmienne lokalne. W ten sposób każdy wątek ma własną wersję każdej zmiennej lokalnej.

Wszystkie zmienne lokalne typów pierwotnych ( boolean , byte , short , char , int , long , float , double ) są w całości przechowywane na stosie wątków i nie są widoczne dla innych wątków. Jeden wątek może przekazać kopię pierwotnej zmiennej do innego wątku, ale nie może współdzielić pierwotnej zmiennej lokalnej.

Sterta

Sterta zawiera wszystkie obiekty utworzone w Twojej aplikacji, niezależnie od tego, który wątek utworzył obiekt. Obejmuje to otoki typów pierwotnych (na przykład Byte , Integer , Long i tak dalej). Nie ma znaczenia, czy obiekt został utworzony i przypisany do zmiennej lokalnej, czy utworzony jako zmienna składowa innego obiektu, jest przechowywany na stercie.

Poniżej znajduje się diagram ilustrujący stos wywołań i zmienne lokalne (są przechowywane na stosach) oraz obiekty (są przechowywane na stercie):

Sterta

W przypadku, gdy zmienna lokalna jest typu pierwotnego, jest przechowywana na stosie wątku.

Zmienna lokalna może być również referencją do obiektu. W tym przypadku odwołanie (zmienna lokalna) jest przechowywane na stosie wątków, ale sam obiekt jest przechowywany na stercie.

Obiekt zawiera metody, metody te zawierają zmienne lokalne. Te zmienne lokalne są również przechowywane na stosie wątków, nawet jeśli obiekt będący właścicielem metody jest przechowywany na stercie.

Zmienne składowe obiektu są przechowywane na stercie wraz z samym obiektem. Dzieje się tak zarówno wtedy, gdy zmienna członkowska jest typu pierwotnego, jak i gdy jest odwołaniem do obiektu.

Statyczne zmienne klasy są również przechowywane na stercie wraz z definicją klasy.

Interakcja z przedmiotami

Dostęp do obiektów na stercie mają wszystkie wątki, które mają odniesienie do obiektu. Jeśli wątek ma dostęp do obiektu, może uzyskać dostęp do zmiennych obiektu. Jeśli dwa wątki wywołają metodę na tym samym obiekcie w tym samym czasie, oba będą miały dostęp do zmiennych składowych obiektu, ale każdy wątek będzie miał własną kopię zmiennych lokalnych.

Interakcja z obiektami (sterta)

Dwa wątki mają zestaw zmiennych lokalnych.Zmienna lokalna 2wskazuje na udostępniony obiekt na stercie (Obiekt 3). Każdy z wątków ma własną kopię zmiennej lokalnej z własnym odwołaniem. Ich odniesienia są zmiennymi lokalnymi i dlatego są przechowywane na stosach wątków. Jednak dwa różne odniesienia wskazują na ten sam obiekt na stercie.

Proszę zauważyć, że generałObiekt 3ma linki doObiekt 2IObiekt 4jako zmienne składowe (pokazane strzałkami). Za pośrednictwem tych łączy dwa wątki mogą uzyskiwać dostępObiekt 2IObiekt4.

Diagram pokazuje również zmienną lokalną (zmienna lokalna 1z metody Two ). Każda jego kopia zawiera różne odniesienia wskazujące na dwa różne obiekty (Obiekt 1IObiekt 5) a nie ten sam. Teoretycznie oba wątki mogą uzyskiwać dostęp do obuObiekt 1, więc doObiekt 5jeśli mają odniesienia do obu tych obiektów. Ale na powyższym diagramie każdy wątek ma odniesienie tylko do jednego z dwóch obiektów.

Przykład interakcji z obiektami

Zobaczmy, jak możemy zademonstrować działanie w kodzie:

public class MySomeRunnable implements Runnable() {

    public void run() {
        one();
    }

    public void one() {
        int localOne = 1;

        Shared localTwo = Shared.instance;

        //... do something with local variables

        two();
    }

    public void two() {
        Integer localOne = 2;

        //... do something with local variables
    }
}
public class Shared {

    // store an instance of our object in a variable

    public static final Shared instance = new Shared();

    // member variables pointing to two objects on the heap

    public Integer object2 = new Integer(22);
    public Integer object4 = new Integer(44);
}

Metoda run() wywołuje metodę one() , a one() z kolei wywołuje metodę two() .

Metoda one() deklaruje pierwotną zmienną lokalną (lokalnyOne) typu int i zmienną lokalną (lokalnyDwa), która jest referencją do obiektu.

Każdy wątek wykonujący metodę one() utworzy własną kopięlokalnyOneIlokalnyDwaw twoim stosie. ZmiennelokalnyOnezostaną całkowicie oddzielone od siebie, będąc na stosie każdego wątku. Jeden wątek nie może zobaczyć, jakie zmiany wprowadza inny wątek w swojej kopiilokalnyOne.

Każdy wątek wykonujący metodę one() tworzy również swoją własną kopięlokalnyDwa. Jednak dwa różne egzemplarzelokalnyDwakończy się wskazaniem tego samego obiektu na stercie. Fakt jest takilokalnyDwawskazuje na obiekt, do którego odwołuje się zmienna statycznainstancja. Istnieje tylko jedna kopia zmiennej statycznej i ta kopia jest przechowywana na stercie.

Więc oba egzemplarzelokalnyDwaw końcu wskazuje na tę samą udostępnioną instancję . Wystąpienie Shared jest również przechowywane na stercie. To pasujeObiekt 3na schemacie powyżej.

Należy zauważyć, że klasa Shared zawiera również dwie zmienne składowe. Same zmienne składowe są przechowywane na stercie wraz z obiektem. Dwie zmienne składowe wskazują na dwa inne obiektyLiczba całkowita. Te obiekty całkowite odpowiadająObiekt 2IObiekt 4na schemacie.

Należy również zauważyć, że metoda two() tworzy zmienną lokalną o nazwielokalnyOne. Ta zmienna lokalna jest odwołaniem do obiektu typu Integer . Metoda ustawia łączelokalnyOneaby wskazać nową instancję typu Integer . Link zostanie zapisany w swojej kopiilokalnyOnedla każdego wątku. Dwie instancje Integer będą przechowywane na stercie, a ponieważ metoda tworzy nowy obiekt Integer za każdym razem, gdy jest wykonywana, dwa wątki wykonujące tę metodę utworzą oddzielne instancje Integer . PasująObiekt 1IObiekt 5na schemacie powyżej.

Zwróć również uwagę na dwie zmienne składowe w Shared klasie typu Integer , która jest typem pierwotnym. Ponieważ te zmienne są zmiennymi składowymi, nadal są przechowywane na stercie wraz z obiektem. W stosie wątków są przechowywane tylko zmienne lokalne.

Komentarze
  • Popularne
  • Najnowsze
  • Najstarsze
Musisz się zalogować, aby dodać komentarz
Ta strona nie ma jeszcze żadnych komentarzy