Maksymalna pamięć Java w systemie Windows XP

103

Zawsze mogłem przydzielić 1400 megabajtów dla Java SE działającej w 32-bitowym systemie Windows XP (Java 1.4, 1.5 i 1.6).

java -Xmx1400m ...

Dzisiaj wypróbowałem tę samą opcję na nowej maszynie z systemem Windows XP z Javą 1.5_16 i 1.6.0_07 i otrzymałem błąd:

Error occurred during initialization of VM
Could not reserve enough space for object heap
Could not create the Java virtual machine.

Metoda prób i błędów wydaje się, że 1200 megabajtów to najwięcej, jakie mogę przeznaczyć na tym komputerze.

Jakieś pomysły, dlaczego jedna maszyna miałaby pozwolić 1400, a inna tylko 1200?

Edycja: maszyna ma 4 GB pamięci RAM i około 3,5 GB, którą może rozpoznać system Windows.

Steve Kuo
źródło
Można zauważyć różnicę w maksimum między uruchomieniem aplikacji w 32-bitowej lub 64-bitowej powłoce, przynajmniej z mojego doświadczenia, chociaż 64-bitowe systemy WindowsXP są rzadkie.
djangofan

Odpowiedzi:

124

Należy pamiętać, że system Windows zarządza pamięcią wirtualną, a maszyna JVM potrzebuje tylko pamięci ciągłej w jej przestrzeni adresowej . Tak więc inne programy działające w systemie nie muszą koniecznie wpływać na rozmiar sterty. Na drodze staną Ci biblioteki DLL, które zostaną załadowane do Twojej przestrzeni adresowej. Niestety optymalizacje w systemie Windows, które minimalizują przenoszenie bibliotek DLL podczas łączenia, zwiększają prawdopodobieństwo, że będziesz mieć pofragmentowaną przestrzeń adresową. Rzeczy, które prawdopodobnie będą przecinać przestrzeń adresową, oprócz zwykłych rzeczy, obejmują oprogramowanie zabezpieczające, oprogramowanie CBT, oprogramowanie szpiegowskie i inne formy złośliwego oprogramowania. Prawdopodobnymi przyczynami rozbieżności są różne poprawki zabezpieczeń, wersje środowiska wykonawczego C itp. Sterowniki urządzeń i inne bity jądra mają swoją własną przestrzeń adresową (pozostałe 2 GB z 4 GB 32-bitowej przestrzeni).

Państwo mogli spróbować przeżywa swoimi powiązaniami DLL w procesie JVM i patrzeć na próby rebase Twój DLL w celu bardziej zwartej przestrzeni adresowej. Nie fajnie, ale jeśli jesteś zdesperowany ...

Alternatywnie możesz po prostu przełączyć się na 64-bitowy system Windows i 64-bitową maszynę JVM. Pomimo tego, co sugerowali inni, podczas gdy spowoduje to większe zużycie pamięci RAM, będziesz mieć znacznie bardziej ciągłą wirtualną przestrzeń adresową, a przydzielanie 2 GB w ciągły sposób byłoby trywialne.

Christopher Smith
źródło
5
Użyj Process Explorer, aby zobaczyć, gdzie w pamięci są ładowane biblioteki DLL. Często jakiś zaktualizowany sterownik przykleja się do środka twojej przestrzeni adresowej. Za pomocą polecenia REBASE możesz łatwo usunąć je z drogi. Należy jednak pamiętać, że biblioteka dll podlega ponownej aktualizacji i zepsuciu rzeczy.
brianegge
2
Nigdy nie zaakceptowałem tego jako odpowiedzi, a mimo to stackoverflow oznaczył to jako odpowiedź.
Steve Kuo
@Christopher, czy można używać 64-bitowej maszyny JVM w 32-bitowym systemie Windows XP?
Pacerier
@Pacerier Przepraszamy, brakowało mi zapytania. AFAIK, to nie jest możliwe. OS X miał kilka sztuczek dla 64-bitowej przestrzeni użytkownika z jądrem 32-bitowym, ale nie słyszałem o czymś takim dla Windowsa.
Christopher Smith
@ChristopherSmith, Btw, wspomniałeś " inne programy działające w systemie nie muszą koniecznie wpływać na rozmiar twojej sterty ". Jeśli tak, jak wyjaśnimy ten wynik: stackoverflow.com/questions/9303889/… ?
Pacerier,
50

Ma to związek z ciągłą pamięcią.

Oto kilka informacji, które znalazłem w Internecie dla kogoś, kto wcześniej o to zapytał, prawdopodobnie od „boga maszyn wirtualnych”:

Powodem, dla którego potrzebujemy ciągłego obszaru pamięci dla sterty, jest to, że mamy kilka bocznych struktur danych, które są indeksowane przez (skalowane) przesunięcia od początku sterty. Na przykład śledzimy aktualizacje odniesień do obiektów za pomocą „tablicy znaków karty”, która ma jeden bajt na każde 512 bajtów sterty. Kiedy przechowujemy odniesienie w stercie, musimy zaznaczyć odpowiedni bajt w tablicy znaczników karty. Przesuwamy w prawo adres docelowy sklepu i używamy go do indeksowania tablicy znaków karty. Zabawne zajmowanie się grami arytmetycznymi, których nie możesz zrobić w Javie, a które możesz (musisz :-) grać w C ++.

Zwykle nie mamy problemów z uzyskaniem skromnych, sąsiadujących regionów (do około 1,5 GB w systemie Windohs, do około 3,8 GB w systemie Solaris. YMMV.). W systemie Windohs problem polega głównie na tym, że niektóre biblioteki są ładowane przed uruchomieniem maszyny JVM i dzielą przestrzeń adresową. Użycie przełącznika / 3GB nie spowoduje zmiany bazy tych bibliotek, więc nadal stanowią dla nas problem.

Wiemy, jak tworzyć stosy kawałków, ale korzystanie z nich wiązałoby się z pewnym obciążeniem. Mamy więcej próśb o szybsze zarządzanie pamięcią masową niż w przypadku większych stert w 32-bitowej JVM. Jeśli naprawdę potrzebujesz dużych stert, przełącz się na 64-bitową maszynę JVM. Nadal potrzebujemy ciągłej pamięci, ale znacznie łatwiej jest uzyskać dostęp do 64-bitowej przestrzeni adresowej.

Uri
źródło
To jest bardzo interesujące. Zawsze zadawałem sobie pytanie, dlaczego 1500 MB, teraz to mam, dzięki!
Tim Büthe
3
Przepraszam, że odpowiadam na stare pytanie, ale to najlepsza odpowiedź, jaką do tej pory widziałem. Ale dlaczego maszyna JVM kończy się niepowodzeniem podczas uruchamiania, jeśli nie może uzyskać maksymalnego rozmiaru sterty? Czy nie powinien po cichu zadowolić się najlepszym rozmiarem powyżej minimum ?
Stroboskop
19

Ograniczenia rozmiaru sterty Java dla systemu Windows to:

  • maksymalny możliwy rozmiar sterty w 32-bitowej Javie: 1,8 GB
  • zalecany limit rozmiaru sterty w 32-bitowej Javie: 1,5 GB (lub 1,8 GB z opcją / 3 GB)

To nie pomaga w uzyskaniu większego stosu Java, ale teraz wiesz, że nie możesz wyjść poza te wartości.

MicSim
źródło
10

Oracle JRockit , który może obsłużyć nieciągłą stertę, może mieć rozmiar sterty Java wynoszący 2,85 GB w systemie Windows 2003 / XP z przełącznikiem / 3GB. Wydaje się, że fragmentacja może mieć duży wpływ na wielkość stosu Java.

Kire Haglin
źródło
6

JVM potrzebuje ciągłej pamięci iw zależności od tego, co jeszcze działa, co działało wcześniej i jak system Windows zarządzał pamięcią, możesz uzyskać do 1,4 GB ciągłej pamięci. Myślę, że 64-bitowy system Windows pozwoli na większe stosy.

James AN Stauffer
źródło
2
Myślę, że nowoczesny system operacyjny emuluje pamięć ciągłą dla. Od modelu 80486 architektura x86 obsługuje stronicowanie, aby ułatwić zmianę układu pamięci fizycznej.
Mnementh
3
Mnemeth: Po pierwsze, w WINAPI istnieje specyficzny interfejs API (AllocateUserPhysicalPages) dla zaawansowanych narzędzi, takich jak bazy danych i maszyny wirtualne, które lepiej radzą sobie z zarządzaniem pamięcią w systemie Windows na uboczu. Po drugie, stronicowanie jest funkcją trybu chronionego 80386, a nie 80486.
Tamas Czinege
6

JVM firmy Sun potrzebuje ciągłej pamięci. Zatem maksymalna ilość dostępnej pamięci jest podyktowana fragmentacją pamięci. Szczególnie biblioteki DLL sterowników mają tendencję do fragmentacji pamięci podczas ładowania do jakiegoś predefiniowanego adresu bazowego. Więc twój sprzęt i jego sterowniki określają, ile pamięci możesz uzyskać.

Dwa źródła z wypowiedziami inżynierów Sun: blog forum

Może inny JVM? Czy próbowałeś Harmony ? Myślę, że planowali zezwolić na pamięć nieciągłą.

the.duckman
źródło
Ale udało mi się przydzielić 1300 MB na maszynie z tylko 1 GB pamięci RAM (plus pamięć wirtualna). Moja maszyna z 2 GB pamięci RAM (również z pamięcią wirtualną) może przydzielić tylko 1200 MB.
Steve Kuo
Harmonia umarła, prawda?
Pacerier,
Tak: „Apache Harmony przeszedł na emeryturę w Apache Software Foundation od 16 listopada 2011 r.”
bobbel
3

Myślę, że ma to więcej wspólnego z konfiguracją systemu Windows, jak wskazuje ta odpowiedź: Java -Xmx Option

Trochę więcej testów: udało mi się przydzielić 1300 MB na starym komputerze z systemem Windows XP z tylko 768 MB fizycznej pamięci RAM (plus pamięć wirtualna). Na moim komputerze z 2 GB pamięci RAM mogę uzyskać tylko 1220 MB. Na różnych komputerach firmowych (ze starszym Windows XP) udało mi się uzyskać 1400MB. Maszyna z limitem 1220 MB jest całkiem nowa (właśnie zakupiona od firmy Dell), więc może ma nowszy (i bardziej rozdęty) system Windows i DLL (działa na nim Windows XP Pro w wersji 2002 SP2).

Steve Kuo
źródło
Może to mieć również wpływ na ustawienia pamięci wirtualnej.
skaffman
Wszystkie testowane przeze mnie maszyny mają pamięć wirtualną co najmniej dwa razy większą niż fizyczna pamięć RAM.
Steve Kuo,
Zauważ, że naprawdę nigdy nie chcesz naprawdę używać pamięci wirtualnej w Javie, ponieważ wydajność GC będzie bardzo niska. Ilość pamięci zależy od tego, które biblioteki dll zostały już załadowane i pofragmentowały pamięć.
kohlerm
2

Otrzymałem ten komunikat o błędzie podczas uruchamiania programu java z (ograniczonej pamięci) wirtualnego serwera VPS. Nie podałem żadnych argumentów pamięci i stwierdziłem, że muszę wyraźnie ustawić niewielką wartość, ponieważ wartość domyślna musiała być zbyt wysoka. Np. -Xmx32m (oczywiście musi być dostrojone w zależności od uruchamianego programu).

Po prostu wstawiam to tutaj na wypadek, gdyby ktoś inny otrzymał powyższy komunikat o błędzie bez określania dużej ilości pamięci, tak jak zrobił to pytający.

William Denniss
źródło
1

JDK / JRE firmy Sun potrzebuje stałej ilości pamięci, jeśli przydzielisz ogromny blok.

System operacyjny i początkowe aplikacje mają tendencję do przydzielania bitów i elementów podczas ładowania, co fragmentuje dostępną pamięć RAM. Jeśli ciągły blok NIE jest dostępny, SUN JDK nie może go użyć. JRockit firmy Bea (nabyty przez Oracle) może przydzielać pamięć z elementów.

anjanb
źródło
1

Wydaje się, że wszyscy odpowiadają na temat pamięci ciągłej, ale zaniedbali dostrzeżenie bardziej palącej kwestii.

Nawet przy 100% ciągłej alokacji pamięci nie można mieć sterty o rozmiarze 2 GiB w 32-bitowym systemie operacyjnym Windows (domyślnie *). Dzieje się tak, ponieważ 32-bitowe procesy systemu Windows nie mogą adresować więcej niż 2 GiB miejsca.

Proces Java będzie zawierał perm gen (przed Java 8), rozmiar stosu na wątek, narzut JVM / biblioteki (który znacznie wzrasta z każdą kompilacją), a wszystko to oprócz sterty .

Ponadto flagi maszyny JVM i ich wartości domyślne zmieniają się między wersjami. Po prostu uruchom poniższe, a zobaczysz jakiś pomysł:

 java -XX:+PrintFlagsFinal

Wiele opcji wpływa na podział pamięci w stercie i poza nią. Pozostawiając ci mniej więcej 2 GiB do gry z ...

Ponowne wykorzystanie części tej odpowiedzi kopalni (około Tomcat, ale odnosi się do każdego procesu Java):

System operacyjny Windows ogranicza alokację pamięci dla procesu 32-bitowego do łącznie 2 GiB (domyślnie).

[Będziesz mógł] przydzielić tylko około 1,5 GiB miejsca na stercie, ponieważ jest też inna pamięć przydzielona procesowi (narzut JVM / biblioteki, przestrzeń perm gen itp.).

Dlaczego 32-bitowy system Windows narzuca 2 GB przestrzeni adresowej procesu, podczas gdy 64-bitowy system Windows nakłada limit 4 GB?

Inne nowoczesne systemy operacyjne [cough Linux] pozwalają 32-bitowym procesom używać całej (lub większości) przestrzeni adresowalnej 4 GiB.

To powiedziawszy, 64-bitowy system operacyjny Windows można skonfigurować tak, aby zwiększyć limit 32-bitowych procesów do 4 GiB (3 GiB w 32-bitowym):

http://msdn.microsoft.com/en-us/library/windows/desktop/aa366778(v=vs.85).aspx

Michael
źródło
1
Ta odpowiedź dotyczy tylko tego, dlaczego może on przydzielić tylko 2 GB, a nie dlaczego może przydzielić 1,4 GB na jednym komputerze i tylko 1,2 GB na innym. Nie przekroczył podanych tutaj limitów 1,5 GB, 2 GB lub 4 GB.
vapcguy
1
Akapit dotyczący flag maszyny JVM w pewien sposób wyjaśnia, dlaczego pamięć może się różnić w zależności od wersji. Zwróć też uwagę na moją uwagę dotyczącą tego, że ustawienie sterty jest zawsze (dużym) ułamkiem całkowitego rozmiaru procesu - więc ustawienie poniżej, które może nadal osiągać limit procesu 2 GiB - inne może być ograniczone przez ciągłą alokację pamięci.
Michael
Lub ewentualnie limit 1,5 GB, na tym przydziale 1,4 GB, który robi. Teraz ma to więcej sensu - dzięki za wyjaśnienie.
vapcguy
0

Oto jak zwiększyć rozmiar stronicowania

  1. kliknij prawym przyciskiem myszy mycomputer ---> properties ---> Advanced
  2. w sekcji wydajności kliknij ustawienia
  3. kliknij kartę Zaawansowane
  4. w sekcji Pamięć wirtualna kliknij Zmień. Pokaże aktualny rozmiar stronicowania.
  5. Wybierz Dysk, na którym jest dostępne miejsce na dysku twardym.
  6. Podaj rozmiar początkowy i maksymalny ... np. Rozmiar początkowy 0 MB i maksymalny rozmiar 4000 MB. (Tyle, ile będziesz potrzebować)
Israel Margulies
źródło
0

** Istnieje wiele sposobów zmiany rozmiaru sterty, np.

  1. file-> setting-> build, exceution, deployment-> compiler tutaj znajdziesz rozmiar sterty
  2. file-> setting-> build, exceution, deployment-> compiler-> andriod tutaj również znajdziesz rozmiar sterty. Możesz skierować to do projektu andriod, jeśli napotkasz ten sam problem.

Dla mnie zadziałało

  1. Ustaw odpowiednią ścieżkę JAVA_HOME na wypadek, gdybyś zaktualizował Java.

  2. utwórz nową zmienną systemową komputer-> właściwości-> ustawienia zaawansowane- > utwórz nową zmienną systemową

nazwa: _JAVA_OPTION wartość: -Xmx750m

Do Twojej wiadomości: możesz znaleźć domyślną opcję VM w pomocy Intellij - > edytuj niestandardową opcję maszyny wirtualnej , w tym pliku widzisz minimalny i maksymalny rozmiar sterty. **

Akanksha gore
źródło
-1

Po pierwsze, używanie pliku stronicowania, gdy masz 4 GB pamięci RAM, jest bezużyteczne. System Windows nie może uzyskać dostępu do więcej niż 4 GB (właściwie mniej z powodu dziur w pamięci), więc plik strony nie jest używany.

Po drugie, przestrzeń adresowa jest podzielona na 2, połowę dla jądra, połowę dla trybu użytkownika. Jeśli potrzebujesz więcej pamięci RAM dla swoich aplikacji, użyj opcji / 3 GB w pliku boot.ini (upewnij się, że plik java.exe jest oznaczony jako „duży adres z uwzględnieniem” (więcej informacji w Google).

Po trzecie, myślę, że nie można przydzielić pełnych 2 GB przestrzeni adresowej, ponieważ java marnuje część pamięci wewnętrznie (na wątki, kompilator JIT, inicjalizację maszyny wirtualnej itp.). Użyj przełącznika / 3GB, aby uzyskać więcej.

user17544
źródło
1
Pomysł, że plik strony jest bezużyteczny z 4 GB lub pamięcią RAM, jest błędny. Bez pliku stronicowania system operacyjny nie może usunąć nieużywanych danych procesowych (miejsca na stosie nieużywanych usług itp.) Z fizycznej pamięci RAM, zmniejszając w ten sposób ilość pamięci RAM dostępnej do rzeczywistej pracy. Posiadanie pliku stronicowania zwalnia pamięć RAM.
nikt