Dlaczego JVM prealokuje pamięć?

0

Uruchamiając jakiś Javovy program należy dodać do JVM przełączniki -Xmx oraz -Xms, które służą zmianie tego, ile pamięci może minimalnie oraz maksymalnie zostać zużytych przez VM-kę.
Moje pytanie brzmi: po co to?
W jakim celu JVM posiada własny memory-allocator, a nie korzysta po prostu z tego systemowego? Jest to wydajniejsze or something?

1

Przełączniki służą do zorganizowania sobie poszczególnych działów pamięci (eden, survivory, perm gen, old gen, stosy dla wątków, itd) oraz chyba dla jakichś uproszczeń w algorytmach - zmniejszanie lub zwiększanie sterty może być problematyczne w JVM.

Poza tym nawet free() czy alloc() nie zawsze (tzn nie przy każdym wywołaniu) korzystają z systemowego alokatora, czyli tego na poziomie jądra systemu. Jak wiadomo dobijanie się do jądra trochę trwa, więc by przyspieszyć działanie nawet free() i malloc() mają mały bufor po stronie procesu użytkownika.

3

Xms to nie minimum, tylko rozmiar startowy.

Zapewne powodem tego maksimum jest to jak działa jvm... JVM nie szuka wolnego miejsca gdy tworzy nowy obiekt, po prostu dodaje go na końcu sterty. Jest to wydajniejsze niż malloc, niestety nie można tego robić w nieskończoność... Miejsce się kiedyś skończy i trzeba odpalić GC. (Xmx można wyznaczyć, by JVM nie zabierał dla siebie całego ramu)

Teoretycznie GC działa w ten sposób, że znajduje "martwe" obiekty (do których nie ma referencji z "żywych"), "usuwa je", po czym przesuwa "żywe" obiekty, by zapełnić te luki po "martwych".

W praktyce przeszukiwanie i przesuwanie takiego np. 3gb pamięci co kilka sekund, powodowałoby niezłe pauzy. Z tego powodu GC w JVM są dzielone na generacje. Mniejszy obszar pamięci (np 100mb) jest przeznaczony na generację "młodą", reszta na "starą". Obiekty są alokowane w młodej generacji, jeśli zacznie tam brakować miejsca, przeprowadzany jest na niej GC. Ponieważ młoda generacja to zwykle mały obszar pamięci, taki gc będzie przeprowadzony bardzo szybko. Jeśli obiekty w tej generacji przeżyją dość długo, zostaną przesunięte do starszej generacji. Dopiero gdy w starszej generacji zacznie brakować miejsca, zostanie odpalony tzw. Full GC.

Generacja może być podzielona na kilka niezależnych bloków, przez co gc może pracować na niej w kilku wątkach, a w młodej generacji nawet wcale nie pauzować działania JVM. Full GC jednak wymaga pauzy.

W Jave 7 doszło G1 GC, któro nie składa się z generacji, tylko po prostu z "niezależnych" bloków pamięci, na których osobno przeprowadza się GC.

1 użytkowników online, w tym zalogowanych: 0, gości: 1