statyczna alokacja w java - generowanie sterty, stosu i trwałe

117

Ostatnio dużo czytałem o schematach alokacji pamięci w Javie i było wiele wątpliwości, które czytałem z różnych źródeł. Zebrałem swoje koncepcje i proszę o przejrzenie wszystkich punktów i skomentowanie ich. Dowiedziałem się, że alokacja pamięci jest specyficzna dla JVM, więc muszę wcześniej powiedzieć, że moje pytanie dotyczy firmy Sun.

  1. Klasy (ładowane przez classloadery) trafiają do specjalnego obszaru na stercie: Permanent Generation
  2. Wszystkie informacje związane z klasą, takie jak nazwa klasy, tablice obiektów powiązane z klasą, wewnętrzne obiekty używane przez JVM (takie jak java / lang / Object) oraz informacje o optymalizacji trafiają do obszaru Generowanie trwałe.
  3. Wszystkie statyczne zmienne składowe są ponownie przechowywane w obszarze trwałej generacji.
  4. Przedmioty trafiają na inny stos: młode pokolenie
  5. Istnieje tylko jedna kopia każdej metody na klasę, statyczna lub niestatyczna. Ta kopia jest umieszczana w obszarze trwałej generacji. W przypadku metod niestatycznych wszystkie parametry i zmienne lokalne trafiają na stos - a za każdym razem, gdy jest konkretne wywołanie tej metody, otrzymujemy nową skojarzoną z nią ramkę stosu. Nie jestem pewien, gdzie są przechowywane zmienne lokalne metody statycznej. Czy są na stercie stałego pokolenia? Lub po prostu ich odniesienie jest przechowywane w obszarze trwałej generacji, a rzeczywista kopia znajduje się gdzie indziej (Gdzie?)
  6. Nie jestem również pewien, gdzie jest przechowywany zwracany typ metody.
  7. Jeśli obiekty (w młodym pokoleniu) muszą używać statycznego elementu członkowskiego (w stałym generowaniu), otrzymują odniesienie do statycznego elementu członkowskiego && mają wystarczająco dużo miejsca w pamięci, aby przechowywać zwracany typ metody itp.

Dziękuję za przejście przez to!

Jaguar
źródło

Odpowiedzi:

152

Po pierwsze, jak już powinno być dla ciebie jasne, że bardzo niewiele osób może potwierdzić te odpowiedzi na podstawie wiedzy z pierwszej ręki. Bardzo niewielu ludzi pracowało nad najnowszymi maszynami JVM HotSpot lub studiowało je dogłębnie, by naprawdę wiedzieć. Większość ludzi tutaj (łącznie ze mną) odpowiada na podstawie rzeczy, które widzieli, napisanych gdzie indziej, lub tego, co wywnioskowali. Zwykle to, co jest napisane tutaj lub w różnych artykułach i stronach internetowych, opiera się na innych źródłach, które mogą być ostateczne lub nie. Często jest to uproszczone, niedokładne lub po prostu błędne.

Jeśli chcesz ostatecznego potwierdzenia swoich odpowiedzi, naprawdę musisz pobrać kod źródłowy OpenJDK ... i przeprowadzić własne badania , czytając i rozumiejąc kod źródłowy. Zadawanie pytań na temat SO lub przeglądanie losowych artykułów w Internecie nie jest dobrą akademicką techniką badawczą.

Powiedziawszy to ...

... moje pytanie dotyczy firmy Sun.

W czasie, gdy zadano to pytanie, Sun Microsystems przestał istnieć. Pytanie było zatem specyficzne dla Oracle. AFAIK, wszystkie obecne (nie badawcze) implementacje JVM innych firm są albo bezpośrednimi portami wersji OpenJDK, albo pochodzą z innej wersji Sun / Oracle.

Poniższe odpowiedzi dotyczą wydań Oracle Hotspot i OpenJDK, a prawdopodobnie także większości innych ... w tym GraalVM.

1) Klasy (ładowane przez classloadery) trafiają do specjalnego obszaru na stercie: Permanent Generation.

Przed wersją Java 8 tak.

Od wersji Java 8 przestrzeń PermGen została zastąpiona Metaspace. Klasy załadowane i skompilowane w JIT są teraz dostępne. PermGen już nie istnieje.

2) Wszystkie informacje związane z klasą, takie jak nazwa klasy, tablice obiektów powiązane z klasą, wewnętrzne obiekty używane przez maszynę JVM (takie jak java / lang / Object) oraz informacje dotyczące optymalizacji trafiają do obszaru Generowanie stałe.

Mniej więcej tak. Nie jestem pewien, co masz na myśli przez niektóre z tych rzeczy. Zgaduję, że „wewnętrzne obiekty używane przez JVM (jak java / lang / Object)” oznacza wewnętrzne deskryptory klas JVM.

3) Wszystkie statyczne zmienne składowe są ponownie przechowywane w obszarze trwałej generacji.

Same zmienne tak. Te zmienne (podobnie jak wszystkie zmienne Java) będą zawierać wartości pierwotne lub odwołania do obiektów. Jednakże, podczas gdy statyczne zmienne składowe znajdują się w ramce, która jest przydzielona w stercie permgen, obiekty / tablice, do których odwołują się te zmienne, mogą być alokowane w dowolnej stercie.

4) Przedmioty trafiają na inną kupę: młode pokolenie

Niekoniecznie. Duże obiekty można przypisać bezpośrednio do wykupionej generacji.

5) W każdej klasie istnieje tylko jedna kopia każdej metody, może być to metoda statyczna lub niestatyczna. Ta kopia jest umieszczana w obszarze trwałej generacji.

Zakładając, że odnosisz się do kodu metody, to AFAIK tak. Może to być jednak trochę bardziej skomplikowane. Na przykład ten kod może istnieć w postaci kodu bajtowego i / lub natywnego w różnych momentach życia maszyny JVM.

... W przypadku metod niestatycznych wszystkie parametry i zmienne lokalne trafiają na stos - a za każdym razem, gdy jest konkretne wywołanie tej metody, otrzymujemy nową skojarzoną z nią ramkę stosu.

Tak.

... Nie jestem pewien, gdzie są przechowywane zmienne lokalne metody statycznej. Czy są na stercie stałego pokolenia? Lub po prostu ich odniesienie jest przechowywane w obszarze trwałej generacji, a rzeczywista kopia znajduje się gdzie indziej (Gdzie?)

Nie. Są przechowywane na stosie, tak jak zmienne lokalne w metodach niestatycznych.

6) Nie jestem również pewien, gdzie jest przechowywany zwracany typ metody.

Jeśli masz na myśli wartość zwracaną przez (nieważne) wywołanie metody, to jest ona zwracana na stosie lub w rejestrze maszynowym. Jeśli zostanie zwrócony na stosie, zajmie to 1 lub dwa słowa, w zależności od typu zwracanego.

7) Jeśli obiekty (w młodym pokoleniu) nie potrzebują statycznego elementu członkowskiego (w stałym generowaniu), otrzymują odniesienie do statycznego elementu członkowskiego && mają wystarczająco dużo miejsca w pamięci, aby przechowywać zwracany typ metody itp. .

To jest niedokładne (a przynajmniej nie wyrażasz się jasno).

Jeśli jakaś metoda uzyskuje dostęp do statycznej zmiennej składowej, otrzymuje albo wartość pierwotną, albo odwołanie do obiektu . Może to być przypisane do (istniejącej) lokalnej zmiennej lub parametru, przypisane do (istniejącego) statycznego lub niestatycznego elementu członkowskiego, przypisane do (istniejącego) elementu wcześniej przydzielonej tablicy lub po prostu użyte i odrzucone.

  • W żadnym przypadku nie trzeba przydzielać nowej pamięci do przechowywania odwołania lub wartości pierwotnej.

  • Zwykle wystarczy jedno słowo pamięci, aby zapisać odwołanie do obiektu lub tablicy, a wartość pierwotna zajmuje zwykle jedno lub dwa słowa, w zależności od architektury sprzętowej.

  • W żadnym przypadku wywołujący nie musi przydzielać miejsca na przechowywanie obiektu / tablicy zwróconej przez metodę. W Javie obiekty i tablice są zawsze zwracane przy użyciu semantyki przekazywania przez wartość ... ale zwracana wartość jest odwołaniem do obiektu lub tablicy.


Aby uzyskać więcej informacji, zapoznaj się z tymi zasobami:

Stephen C.
źródło