Gdzie są metody statyczne i zmienne statyczne przechowywane w Javie?

116

Na przykład:

class A {
    static int i=0;
    static int j;

   static void method() {
       // static k=0; can't use static for local variables only final is permitted
       // static int L;
    }
}

Gdzie te zmienne będą przechowywane w Javie, na stercie lub w pamięci stosu? Jak są przechowywane?

Nav
źródło
2
bardzo przydatny link do zrozumienia zbierania śmieci na oficjalnej stronie Oracle: oracle.com/webfolder/technetwork/tutorials/obe/java/gc01/…
Arnav Joshi

Odpowiedzi:

144

Metody statyczne (w rzeczywistości wszystkie metody), a także zmienne statyczne są przechowywane w PermGensekcji sterty, ponieważ są częścią danych odbicia (dane związane z klasą, a nie z instancją).

Aktualizacja w celu wyjaśnienia :

Zauważ, że tylko zmienne i ich wartości techniczne (prymitywy lub referencje) są przechowywane w przestrzeni PermGen.

Jeśli zmienna statyczna jest odniesieniem do obiektu, sam obiekt jest przechowywany w normalnych sekcjach sterty (przestrzeń młodego / starego pokolenia lub ocalałego). Te obiekty (chyba że są to obiekty wewnętrzne, takie jak klasy itp.) Nie są przechowywane w przestrzeni PermGen.

Przykład:

static int i = 1; //the value 1 is stored in the PermGen section
static Object o = new SomeObject(); //the reference(pointer/memory address) is stored in the PermGen section, the object itself is not.


Słowo na temat zbierania śmieci:

Czy nie polegać na finalize(), ponieważ nie ma gwarancji, aby uruchomić. To JVM całkowicie decyduje, kiedy uruchomić moduł odśmiecania pamięci i co zbierać, nawet jeśli obiekt kwalifikuje się do czyszczenia pamięci.

Oczywiście można ustawić zmienną statyczną na null, a tym samym usunąć odwołanie do obiektu na stercie, ale to nie znaczy, garbage collector będzie je zbierać (nawet jeśli nie ma więcej odniesień).

Dodatkowo finalize()jest uruchamiany tylko raz, więc musisz się upewnić, że nie zgłasza wyjątków lub w inny sposób nie zapobiega gromadzeniu obiektu. Jeśli zatrzymasz finalizację finalize()z powodu jakiegoś wyjątku, nie zostanie wywołany na tym samym obiekcie po raz drugi.

Ostatnia uwaga : sposób przechowywania kodu, danych uruchomieniowych itp. Zależy od używanej maszyny JVM, tj. HotSpot może robić to inaczej niż JRockit, a to może się nawet różnić między wersjami tej samej maszyny JVM. Powyższe jest oparte na HotSpot dla Javy 5 i 6 (te są w zasadzie takie same), ponieważ w momencie odpowiadania powiedziałbym, że większość ludzi korzystała z tych maszyn JVM. Ze względu na duże zmiany w modelu pamięci od wersji Java 8 powyższe stwierdzenia mogą nie być prawdziwe dla Java 8 HotSpot - i nie sprawdzałem zmian w Java 7 HotSpot, więc myślę, że powyższe jest nadal prawdziwe dla tej wersji, ale tutaj nie jestem pewien.

Tomasz
źródło
1
Ahh czy jesteś pewien co do zmiennych statycznych? AFAIK PermGen przechowuje tylko definicje, a nie rzeczywistą wartość.
Amir Raminfar
2
@Amir Jestem prawie pewien, że sama zmienna jest przechowywana w przestrzeni permgen, każdy obiekt, do którego się odwołuje, najprawdopodobniej zostanie przydzielony na stercie. To może dodać trochę informacji: stackoverflow.com/questions/3800444/…
Thomas
1
Ach tak, definicja zmiennej jest przechowywana w permgen. Ale wartość będzie na kupie. Twoja odpowiedź sugeruje, że wartość jest również przechowywana w PermGen.
Amir Raminfar,
1
@Matthew, jak rozumiesz moją odpowiedź? A powiedział, że zmienne są przechowywane w sekcji permgen (elementy podstawowe / odniesienia), a nie obiekty, do których się odnoszą. Zależy to od sposobu wyświetlania wartości zmiennych .
Thomas,
1
@Nav nie wszystkie części sterty są domyślnie zbierane jako elementy bezużyteczne i czasami nie można zbierać klas, a tym samym zmiennych statycznych, ponieważ programy ładujące klasy nadal mają do nich odniesienie. Dodatkowo nie powinieneś polegać na zbieraczu elementów bezużytecznych, ponieważ jest to całkowicie zależne od JVM (decyduje, kiedy uruchomić i co zebrać, możesz podać tylko wskazówki typu „Chciałbym, abyś teraz uruchomił gc” :)) .
Thomas,
25

Zmienne klasowe (zmienne statyczne) są przechowywane jako część Class objectpowiązana z tą klasą. Ten obiekt klasy może zostać utworzony tylko przez maszynę JVM i jest przechowywany w plikach permanent generation.

Niektórzy również odpowiedzieli, że jest przechowywany w obszarze innym niż sterta, który nazywa się Method Area.Nawet ta odpowiedź nie jest błędna. Jest to tylko dyskusyjny temat, czy Permgen Area jest częścią sterty, czy nie. Oczywiście postrzeganie różni się w zależności od osoby. Moim zdaniem w argumentach JVM w różny sposób zapewniamy przestrzeń sterty i przestrzeń permgen. Dlatego dobrym założeniem jest traktowanie ich inaczej.

Inny sposób, aby to zobaczyć

Pule pamięci są tworzone przez menedżerów pamięci maszyny JVM w czasie wykonywania. Pula pamięci może należeć do pamięci sterty lub pamięci innej niż sterta. Pula stałych czasu wykonywania jest reprezentacją tabeli puli stałych w pliku klasy w czasie wykonywania na klasę lub interfejs. Każda pula stałych czasu wykonywania jest przydzielana z obszaru metod wirtualnej maszyny języka Java, a zmienne statyczne są przechowywane w tym obszarze metod. Również ten non-heap to nic innego jak obszar perm gen. Właściwie obszar Method jest częścią perm gen. ( Odniesienie )

wprowadź opis obrazu tutaj

Aniket Thakur
źródło
czy obszar metody nie jest podzbiorem sekcji PermGen pamięci? Dlaczego pokazałeś obszar metody jako część pamięci innej niż sterta, skoro, jak sądzę, (PermGen wraz z obszarem metody (klasy)) są częścią większego obszaru sterty maszyny JVM?
Kaveesh Kanwal
Przeczytaj ostatnią linijkę -Also this non-heap is nothing but perm gen area.Actually Method area is part of perm gen.
Aniket Thakur
1
@AniketThakur pokazałeś obszar metody jako część pamięci innej niż sterta, ale zgodnie z dokumentami oracle, tutaj, docs.oracle.com/javase/specs/jvms/se7/html/ ... wspomniano, że obszar metody jest logiczną częścią kupa.
Karan
21

Przed Java 8:

Zmienne statyczne były przechowywane w przestrzeni permgen (nazywanej również obszarem metody).

PermGen Space jest również znany jako Method Area

PermGen Space służyło do przechowywania 3 rzeczy

  1. Dane na poziomie klasy (metadane)
  2. internowane struny
  3. zmienne statyczne

Od wersji Java 8

Zmienne statyczne są przechowywane w samej sterty. Począwszy od Java 8, przestrzeń PermGen została usunięta i wprowadzono nową przestrzeń nazwaną MetaSpace, która nie jest już częścią Heap w przeciwieństwie do poprzedniej Permgen Space. Meta-Space jest obecna w pamięci natywnej (pamięć dostarczana przez system operacyjny do określonej aplikacji na jej własny użytek) i teraz przechowuje tylko metadane klasy.

Wewnętrzne ciągi i zmienne statyczne są przenoszone do samej sterty.

Oficjalne informacje można znaleźć w: JEP 122: Remove the Permanent Gen Space

Manish Kumar
źródło
kiedy mówisz „sterta sama” dla zmiennych statycznych> Java8, gdzie dokładnie: OldGen?
Ewoks
15

To jest pytanie z prostą odpowiedzią i rozwlekłą odpowiedzią.

Prosta odpowiedź brzmi: kupa. Klasy i wszystkie dane dotyczące klas (nie dane instancji) są przechowywane w sekcji Stałe generowanie sterty.

Długa odpowiedź jest już na przepełnieniu stosu:

Istnieje dokładny opis pamięci i czyszczenia pamięci w JVM, a także odpowiedź, która mówi o tym bardziej zwięźle .

Wasilij Szarapow
źródło
3
Jasne! Nie zapomnij zagłosować za tych gości, jeśli uznasz ich za przydatnych.
Wasilij Szarapow
11

Jest przechowywany w stercie, do którego odwołuje się definicja klasy. Jeśli się nad tym zastanowić, nie ma to nic wspólnego ze stosem, ponieważ nie ma zasięgu.

Amir Raminfar
źródło
5

Oprócz odpowiedzi Thomasa, zmienne statyczne są przechowywane w obszarze innym niż sterta, który jest nazywany obszarem metod.

Vipin
źródło
4

Ponieważ zmienne statyczne są zmiennymi na poziomie klasy, będą one przechowywać „ trwałe generowanie ” pamięci sterty. Zapoznaj się z tym, aby uzyskać więcej informacji na temat maszyny JVM. Mam nadzieję, że to okaże się pomocne

Ramesh Papaganti
źródło
3

zmienne statyczne są przechowywane w stercie

CLS
źródło
7
Zmienne statyczne są przechowywane w przestrzeni PremGen w pamięci, ich wartości są przechowywane w Heap.
Akash5288