Maksymalny rozmiar sterty Java 32-bitowej maszyny JVM w 64-bitowym systemie operacyjnym


107

Pytanie nie dotyczy maksymalnego rozmiaru sterty w 32-bitowym systemie operacyjnym, biorąc pod uwagę, że 32-bitowe systemy operacyjne mają maksymalny rozmiar adresowalnej pamięci wynoszący 4 GB, a maksymalny rozmiar sterty maszyny JVM zależy od tego, ile ciągłej wolnej pamięci można zarezerwować.

Bardziej interesuje mnie znajomość maksymalnego (zarówno teoretycznego, jak i praktycznie osiągalnego) rozmiaru sterty dla 32-bitowej maszyny JVM działającej w 64-bitowym systemie operacyjnym. Zasadniczo szukam odpowiedzi podobnych do liczb w powiązanym pytaniu dotyczącym SO .

Jeśli chodzi o to, dlaczego używana jest 32-bitowa JVM zamiast 64-bitowej, przyczyna nie jest techniczna, ale raczej administracyjna / biurokratyczna - prawdopodobnie jest za późno na zainstalowanie 64-bitowej maszyny JVM w środowisku produkcyjnym.

Odpowiedzi:


70

32-bitowe maszyny JVM, które spodziewają się mieć jeden duży fragment pamięci i używają surowych wskaźników, nie mogą używać więcej niż 4 Gb (ponieważ jest to limit 32-bitowy, który dotyczy również wskaźników). Obejmuje to Sun i - jestem pewien - także implementacje IBM. Nie wiem, czy np. JRockit czy inne mają opcję dużej pamięci w swoich 32-bitowych implementacjach.

Jeśli spodziewasz się osiągnąć ten limit, zdecydowanie powinieneś rozważyć rozpoczęcie równoległej ścieżki sprawdzającej poprawność 64-bitowej maszyny JVM dla środowiska produkcyjnego, aby mieć to przygotowane na wypadek awarii środowiska 32-bitowego. W przeciwnym razie będziesz musiał wykonywać tę pracę pod presją, co nigdy nie jest przyjemne.


Edycja 2015-05-15: Często zadawane pytania dotyczące Oracle:

Maksymalny teoretyczny limit sterty dla 32-bitowej maszyny JVM to 4G. Ze względu na różne dodatkowe ograniczenia, takie jak dostępna wymiana, wykorzystanie przestrzeni adresowej jądra, fragmentacja pamięci i narzut maszyny wirtualnej, w praktyce limit może być znacznie niższy. W większości nowoczesnych 32-bitowych systemów Windows maksymalny rozmiar sterty będzie wynosić od 1,4 GB do 1,6 GB. W 32-bitowych jądrach Solaris przestrzeń adresowa jest ograniczona do 2G. W 64-bitowych systemach operacyjnych z 32-bitową maszyną wirtualną maksymalny rozmiar sterty może być większy, zbliżając się do 4G w wielu systemach Solaris.

( http://www.oracle.com/technetwork/java/hotspotfaq-138619.html#gc_heap_32bit )


Brak presji w pracy. Wiem, że w pierwszej kolejności należało zainstalować 64-bitową maszynę JVM. Ale to sprawiło, że pomyślałem o tym, jak 32-bitowa maszyna JVM mogłaby działać w środowisku z większą ilością zasobów do dyspozycji.
Vineet Reynolds

1
Czy to nie około 2 GB ze względu na podpisy? A może to tylko Sun JVM?
Sebastian Ganslandt

9
Wskaźniki nie są podpisane - nie ma sensu mówić o negatywnych lokalizacjach pamięci.
Thorbjørn Ravn Andersen

12
Nie, to nie jest 2 GB ze względu na podpis. Jednak część przestrzeni adresowej 4 GB jest zarezerwowana dla jądra systemu operacyjnego. W normalnych konsumenckich wersjach systemu Windows limit wynosi 2 GB. W systemach Linux i serwerowych wersjach systemu Windows (32-bitowych) limit wynosi 3 GB na proces.
Jesper

3
@Jesper Zastanawiałem się, czy 32-bitowa JVM działająca w 64-bitowym systemie operacyjnym mogłaby mieć pełną dostępną przestrzeń adresową 4 GB?
Thorbjørn Ravn Andersen,

90

Możesz zapytać Java Runtime:

public class MaxMemory {
    public static void main(String[] args) {
        Runtime rt = Runtime.getRuntime();
        long totalMem = rt.totalMemory();
        long maxMem = rt.maxMemory();
        long freeMem = rt.freeMemory();
        double megs = 1048576.0;

        System.out.println ("Total Memory: " + totalMem + " (" + (totalMem/megs) + " MiB)");
        System.out.println ("Max Memory:   " + maxMem + " (" + (maxMem/megs) + " MiB)");
        System.out.println ("Free Memory:  " + freeMem + " (" + (freeMem/megs) + " MiB)");
    }
}

Spowoduje to zgłoszenie „Max Memory” w oparciu o domyślną alokację sterty. Więc nadal musisz grać z -Xmx(na HotSpot ). Zauważyłem, że działając w 64-bitowym systemie Windows 7 Enterprise, moja 32-bitowa maszyna JVM HotSpot może przydzielić do 1577 MiB:

[C: scratch]> java -Xmx1600M MaxMemory
Wystąpił błąd podczas inicjowania maszyny wirtualnej
Nie można zarezerwować wystarczającej ilości miejsca na stertę obiektów
Nie można utworzyć wirtualnej maszyny Java.
[C: scratch]> java -Xmx1590M MaxMemory
Całkowita pamięć: 2031616 (1,9375 MiB)
Pamięć maksymalna: 1654456320 (1577,8125 MiB)
Wolna pamięć: 1840872 (1,75559234619 MiB)
[C: podstaw]>

Podczas gdy w przypadku 64-bitowej maszyny JVM w tym samym systemie operacyjnym jest oczywiście znacznie wyższy (około 3 TiB)

[C: scratch]> java -Xmx3560G MaxMemory
Wystąpił błąd podczas inicjowania maszyny wirtualnej
Nie można zarezerwować wystarczającej ilości miejsca na stertę obiektów
[C: scratch]> java -Xmx3550G MaxMemory
Całkowita pamięć: 94240768 (89,875 MiB)
Maks. Pamięć: 3388252028928 (3184151,84297 MiB)
Wolna pamięć: 93747752 (89,4048233032 MiB)
[C: podstaw]>

Jak już wspominali inni, zależy to od systemu operacyjnego.

  • W przypadku 32-bitowego systemu Windows: będzie to <2 GB ( książka wewnętrzna systemu Windows mówi o 2 GB na procesy użytkownika)
  • Dla 32-bitowego BSD / Linux: <3 GB (z Devil Book)
  • 32-bitowy MacOS X: <4 GB (z książki wewnętrznej Mac OS X )
  • Nie jesteś pewien co do 32-bitowego systemu Solaris, wypróbuj powyższy kod i daj nam znać.

W przypadku 64-bitowego systemu operacyjnego hosta, jeśli JVM jest 32-bitowa, nadal będzie zależeć, najprawdopodobniej jak powyżej, jak pokazano.

- UPDATE 20110905 : Chciałem tylko wskazać kilka innych obserwacji / szczegółów:

  • Sprzęt, na którym to uruchomiłem, był 64-bitowy z zainstalowanymi 6 GB rzeczywistej pamięci RAM. System operacyjny to Windows 7 Enterprise, 64-bitowy
  • Rzeczywista kwota, Runtime.MaxMemoryjaką można przydzielić, zależy również od zestawu roboczego systemu operacyjnego . Kiedyś uruchomiłem to, gdy miałem również uruchomiony VirtualBox i stwierdziłem, że nie mogę pomyślnie uruchomić maszyny wirtualnej HotSpot JVM -Xmx1590Mi musiałem zmniejszyć jej rozmiar. Oznacza to również, że możesz uzyskać więcej niż 1590 M, w zależności od rozmiaru zestawu roboczego w danym momencie (chociaż nadal utrzymuję, że będzie poniżej 2 GB dla 32-bitów ze względu na projekt systemu Windows)

13
Podoba mi się, że faktycznie testowałeś, zamiast zgadywać.
Jim Hurne,

3
@djangofan ma rację. Program powinien dzielić przez 1048576 (1024 * 1024 lub 2 ^ 20), a nie przez 104 856. Ale to tylko ekspozycja. Jak widać z polecenia, próbował tylko ustawić maksymalny rozmiar sterty na 1590 MiB.
Jim Hurne,

1
Bardzo fajna odpowiedź (chciałbym powiedzieć na odpowiedź), z przykładu kod i dane obejmujące wszystkie systemów operacyjnych.
TGP1994,

3
Nawiązując do mojego poprzedniego komentarza: jdocs (przynajmniej dla Windows) określają, że parametry -Xmx i -Xms muszą mieć wartość będącą wielokrotnością 1024 ... Nie jestem pewien, czy 1590 to jest, więc myślę dziwnie należy się spodziewać wyników.
TGP1994,

4
Dobrze zauważony TGP1994. Myślę, że ponieważ określiłem wielokrotności „M” i „G”, to rozmiar (w bajtach) i tak będzie wielokrotnością 1024 bajtów. np. 1590M zostanie przeanalizowane do 1590 * (1024 * 1024) = 1667235840 bajtów (1628160KiB - parzysta wielokrotność 1024).
mike

16

Nie określasz, który system operacyjny.

W systemie Windows (dla mojej aplikacji - długo działającej aplikacji do zarządzania ryzykiem) zauważyliśmy, że nie możemy przejść dalej niż 1280 MB na 32-bitowym systemie Windows. Wątpię, czy uruchomienie 32-bitowej maszyny JVM pod 64-bitową miało jakiekolwiek znaczenie.

Przenieśliśmy aplikację na Linuksa i używamy 32-bitowej maszyny JVM na 64-bitowym sprzęcie i mamy maszynę wirtualną 2,2 GB działającą dość łatwo.

Największym problemem, jaki możesz mieć, jest GC w zależności od tego, do czego używasz pamięci.


Wolałbym znać ograniczenie dla Solaris 10, ale wtedy dotyczy to tylko mojego problemu. Chciałbym wiedzieć także o innych systemach operacyjnych, na deszczowy dzień :)
Vineet Reynolds

Nie jestem pewien co do Solaris. Spodziewałbym się, że rozmiar maszyny wirtualnej będzie dość duży, moje doświadczenie z Javą na Solarisie pochodziło z kilku lat temu. A bycie maszyną wirtualną firmy Sun w systemie operacyjnym Sun na sprzęcie firmy Sun - wszystko działało całkiem dobrze. Doszedłem również do wniosku, że w Solarisie jest mniej problemów z GC niż w Linuksie / Windowsie.
Fortyrunner

Który to był Windows. Uważam, że 32-bitowe wersje systemu Windows na serwerach znacznie lepiej radzą sobie z dużymi ilościami pamięci.
Thorbjørn Ravn Andersen

Ach, na koniec wzmianka o systemie operacyjnym ;-) Masz zainstalowane jądro 64-bitowe?
Thorbjørn Ravn Andersen

Był to serwer Win2k. Przejście na Win2k3 (rzeczy toczą się powoli…) było za późno i zamiast tego przeszliśmy na Linuksa.
Fortyrunner

14

Od 4.1.2 Rozmiar sterty :

„W przypadku 32-bitowego modelu procesu maksymalny rozmiar adresu wirtualnego procesu wynosi zwykle 4 GB, chociaż niektóre systemy operacyjne ograniczają ten rozmiar do 2 GB lub 3 GB. Maksymalny rozmiar sterty wynosi zwykle -Xmx3800m (1600m) dla limitów 2 GB ), chociaż faktyczne ograniczenie jest zależne od aplikacji. W przypadku 64-bitowych modeli procesów maksymalna wartość jest zasadniczo nieograniczona. "

Znalazłem tutaj całkiem dobrą odpowiedź: maksymalna pamięć Java w systemie Windows XP .


12

Niedawno mieliśmy z tym pewne doświadczenia. Niedawno przeportowaliśmy system z Solaris (x86-64 wersja 5.10) na Linux (RedHat x86-64) i zdaliśmy sobie sprawę, że mamy mniej dostępnej pamięci dla 32-bitowego procesu JVM w systemie Linux niż Solaris.

W przypadku Solaris to prawie 4 GB (http://www.oracle.com/technetwork/java/hotspotfaq-138619.html#gc_heap_32bit).

Uruchomiliśmy naszą aplikację z -Xms2560m -Xmx2560m -XX: MaxPermSize = 512m -XX: PermSize = 512m bez żadnych problemów w systemie Solaris przez ostatnie kilka lat. Próbowałem przenieść go na Linuksa i mieliśmy problemy z losowymi błędami braku pamięci podczas uruchamiania. Mogliśmy tylko sprawić, by konsekwentnie uruchamiał się na -Xms2300 -Xmx2300 . Następnie poinformowano nas o tym przez wsparcie.

32-bitowy proces w systemie Linux ma maksymalną adresowalną przestrzeń adresową 3 GB (3072 MB), podczas gdy w systemie Solaris jest to pełne 4 GB (4096 MB).


Przyczyną odpowiedzi udzielonej przez obsługę jest to, ile pamięci adresowalnej jest dostępne dla procesu. Zależy to od jądra Linuksa, a nawet od sprzętu. Teoretycznie pamięć adresowalna jest ograniczona do 2 ^ 32 = 4G (a rozmiar sterty Java byłby mniejszy). Ale można to (teoretycznie) rozszerzyć za pomocą hugemem i PAE; Nie próbowałem tego.
Vineet Reynolds

9

Ograniczenia 32-bitowej maszyny JVM w 64-bitowym systemie operacyjnym będą dokładnie takie same, jak ograniczenia 32-bitowej maszyny JVM w 32-bitowym systemie operacyjnym. W końcu 32-bitowa JVM będzie działać na 32-bitowej maszynie wirtualnej (w sensie wirtualizacji), więc nie będzie wiedzieć, że działa na 64-bitowym systemie operacyjnym / maszynie.

Jedyną zaletą uruchamiania 32-bitowej maszyny JVM w 64-bitowym systemie operacyjnym w porównaniu z 32-bitowym systemem operacyjnym jest to, że można mieć więcej pamięci fizycznej i dlatego rzadziej napotyka wymianę / stronicowanie. Ta zaleta jest jednak w pełni widoczna tylko wtedy, gdy masz wiele procesów.


1
Może występować niewielka różnica w zależności od sprzętu i sposobu jego wirtualizacji. Część przestrzeni adresowalnej 4 GB jest zwykle używana przez urządzenia mapowane w pamięci. Warstwa wirtualizacji może mieć taki sam ślad pamięci, jak fizyczne urządzenia na komputerze, ale nie musi.
Eric J.

8
Nie do końca. Jest więcej miejsca dla maszyny JVM w 64-bitowej maszynie, ponieważ 32-bitowa przestrzeń adresowa nie musi być współużytkowana z systemem operacyjnym lub interfejsami sprzętowymi.
Thorbjørn Ravn Andersen

To prawda, ale wszystko to oznacza, że ​​twoja 32-bitowa maszyna wirtualna może mieć nieco inny narzut niż rzeczywista maszyna 32-bitowa (gorsza lub lepsza). Tak czy inaczej, uruchamiasz maszynę JVM na maszynie 32-bitowej (rzeczywistej lub wirtualnej), więc będziesz podlegać standardowym ograniczeniom 32-bitowym. tj .: bezwzględny pułap 4 GB.
Laurence Gonsalves,

Thorbjørn: system operacyjny i interfejsy sprzętowe nadal wymagają mapowania na 32-bitową maszynę wirtualną. Dokładna liczba podsłuchanych może być inna, ale nadal tam będzie. Jeśli możesz go zwirtualizować w 64-bitowym systemie operacyjnym, co powstrzyma Cię przed wirtualizacją w 32-bitowym systemie operacyjnym? To jest pamięć wirtualna , o której mówimy.
Laurence Gonsalves,

2
LG: Nie zgadzam się z Twoją pierwotną odpowiedzią. Jądro systemu operacyjnego i wszelka przestrzeń adresowa sprzętu i magistrali, które mapuje, zużyją dużo przestrzeni adresowej i chociaż nie jest to mapowane do programu użytkownika, zmniejsza ilość „pozostałej” po skonfigurowaniu systemu operacyjnego. To znaczna ilość z 4 GB 32-bitowej przestrzeni. Tradycyjnie oznaczało to, że około 25% -75% z 4 GB jest niedostępnych dla procesów użytkownika. :-) haker jądra
DigitalRoss

6

Co do tego, dlaczego używana jest 32-bitowa maszyna JVM zamiast 64-bitowej, przyczyna nie jest techniczna, ale raczej administracyjna / biurokratyczna ...

Kiedy pracowałem dla BEA, stwierdziliśmy, że przeciętna aplikacja faktycznie działała wolniej w 64-bitowej JVM, niż działała na 32-bitowej JVM. W niektórych przypadkach wydajność była nawet o 25% wolniejsza. Tak więc, chyba że Twoja aplikacja naprawdę potrzebuje całej tej dodatkowej pamięci, lepiej byłoby skonfigurować więcej serwerów 32-bitowych.

Jak sobie przypominam, trzy najczęstsze techniczne uzasadnienia korzystania z 64-bitowej wersji, z którymi zetknął się personel serwisowy BEA to:

  1. Aplikacja manipulowała wieloma ogromnymi obrazami,
  2. Aplikacja przetwarzała ogromne liczby,
  3. Aplikacja miała wyciek pamięci, klient był pierwszy na kontrakcie rządowym i nie chciał poświęcać czasu i kosztów na śledzenie wycieku pamięci. (Korzystanie z ogromnej sterty pamięci zwiększyłoby MTBF, a pierwsza nadal byłaby opłacana)

.


Miło, że udzielasz porad z pierwszej ręki, były pracownik BEA :)
emecas

4

JROCKIT JVM aktualnie należąca do Oracle obsługuje nieciągłe użycie sterty, dzięki czemu 32-bitowa maszyna JVM może uzyskać dostęp do ponad 3,8 GB pamięci, gdy maszyna JVM działa w 64-bitowym systemie operacyjnym Windows. (2,8 GB w przypadku 32-bitowego systemu operacyjnego).

http://blogs.oracle.com/jrockit/entry/how_to_get_almost_3_gb_heap_on_windows

JVM można bezpłatnie pobrać (wymagana rejestracja) pod adresem

http://www.oracle.com/technetwork/middleware/jrockit/downloads/index.html


4

Oto kilka testów pod Solaris i Linux 64-bit

Solaris 10 - SPARC - maszyna T5220 z 32 GB RAM (i około 9 GB wolnego)

$ java -XX:PermSize=128M -XX:MaxPermSize=256M -Xms512m -Xmx3750m MaxMemory
Error occurred during initialization of VM
Could not reserve space for ObjectStartArray
$ java -XX:PermSize=128M -XX:MaxPermSize=256M -Xms512m -Xmx3700m MaxMemory
Total Memory: 518520832 (494.5 MiB)
Max Memory:   3451912192 (3292.0 MiB)
Free Memory:  515815488 (491.91998291015625 MiB)
Current PID is: 28274
Waiting for user to press Enter to finish ...

$ java -version
java version "1.6.0_30"
Java(TM) SE Runtime Environment (build 1.6.0_30-b12)
Java HotSpot(TM) Server VM (build 20.5-b03, mixed mode)

$ which java
/usr/bin/java
$ file /usr/bin/java
/usr/bin/java: ELF 32-bit MSB executable SPARC Version 1, dynamically linked, not stripped, no debugging information available

$ prstat -p 28274
   PID USERNAME  SIZE   RSS STATE  PRI NICE      TIME  CPU PROCESS/NLWP
28274 user1     670M   32M sleep   59    0   0:00:00 0.0% java/35

BTW: Najwyraźniej Java nie przydziela dużo pamięci podczas uruchamiania. Wydawało się, że zajęło to tylko około 100 MB na uruchomioną instancję (zacząłem 10)

Solaris 10 - x86 - VMWare VM z 8 GB RAM (około 3 GB wolnego *)

3 GB wolnej pamięci RAM nie jest prawdą. Jest duży fragment pamięci RAM, którego używają pamięci podręczne ZFS, ale nie mam uprawnień administratora, aby sprawdzić, ile dokładnie

$ java -XX:PermSize=128M -XX:MaxPermSize=256M -Xms512m -Xmx3650m MaxMemory
Error occurred during initialization of VM
Could not reserve enough space for object heap
Could not create the Java virtual machine.

$ java -XX:PermSize=128M -XX:MaxPermSize=256M -Xms512m -Xmx3600m MaxMemory
Total Memory: 516423680 (492.5 MiB)
Max Memory:   3355443200 (3200.0 MiB)
Free Memory:  513718336 (489.91998291015625 MiB)
Current PID is: 26841
Waiting for user to press Enter to finish ...

$ java -version
java version "1.6.0_41"
Java(TM) SE Runtime Environment (build 1.6.0_41-b02)
Java HotSpot(TM) Server VM (build 20.14-b01, mixed mode)

$ which java
/usr/bin/java

$ file /usr/bin/java
/usr/bin/java:  ELF 32-bit LSB executable 80386 Version 1 [FPU], dynamically linked, not stripped, no debugging information available

$ prstat -p 26841
   PID USERNAME  SIZE   RSS STATE  PRI NICE      TIME  CPU PROCESS/NLWP
26841 user1     665M   22M sleep   59    0   0:00:00 0.0% java/12

RedHat 5.5 - x86 - VMWare VM z 4 GB RAM (używane około 3,8 GB - 200 MB w buforach i 3,1 GB w pamięci podręcznej, czyli około 3 GB wolnego)

$ alias java='$HOME/jre/jre1.6.0_34/bin/java'

$ java -XX:PermSize=128M -XX:MaxPermSize=256M -Xms512m -Xmx3500m MaxMemory
Error occurred during initialization of VM
Could not reserve enough space for object heap
Could not create the Java virtual machine.

$ java -XX:PermSize=128M -XX:MaxPermSize=256M -Xms512m -Xmx3450m MaxMemory
Total Memory: 514523136 (490.6875 MiB)
Max Memory:   3215654912 (3066.6875 MiB)
Free Memory:  511838768 (488.1274871826172 MiB)
Current PID is: 21879
Waiting for user to press Enter to finish ...

$ java -version
java version "1.6.0_34"
Java(TM) SE Runtime Environment (build 1.6.0_34-b04)
Java HotSpot(TM) Server VM (build 20.9-b04, mixed mode)

$ file $HOME/jre/jre1.6.0_34/bin/java
/home/user1/jre/jre1.6.0_34/bin/java: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), for GNU/Linux 2.2.5, dynamically linked (uses shared libs), for GNU/Linux 2.2.5, not stripped

$ cat /proc/21879/status | grep ^Vm
VmPeak:  3882796 kB
VmSize:  3882796 kB
VmLck:         0 kB
VmHWM:     12520 kB
VmRSS:     12520 kB
VmData:  3867424 kB
VmStk:        88 kB
VmExe:        40 kB
VmLib:     14804 kB
VmPTE:        96 kB

Ta sama maszyna korzystająca z JRE 7

$ alias java='$HOME/jre/jre1.7.0_21/bin/java'

$ java -XX:PermSize=128M -XX:MaxPermSize=256M -Xms512m -Xmx3500m MaxMemory
Error occurred during initialization of VM
Could not reserve enough space for object heap
Error: Could not create the Java Virtual Machine.
Error: A fatal exception has occurred. Program will exit.

$ java -XX:PermSize=128M -XX:MaxPermSize=256M -Xms512m -Xmx3450m MaxMemory
Total Memory: 514523136 (490.6875 MiB)
Max Memory:   3215654912 (3066.6875 MiB)
Free Memory:  511838672 (488.1273956298828 MiB)
Current PID is: 23026
Waiting for user to press Enter to finish ...

$ java -version
java version "1.7.0_21"
Java(TM) SE Runtime Environment (build 1.7.0_21-b11)
Java HotSpot(TM) Server VM (build 23.21-b01, mixed mode)

$ file $HOME/jre/jre1.7.0_21/bin/java
/home/user1/jre/jre1.7.0_21/bin/java: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), for GNU/Linux 2.6.9, dynamically linked (uses shared libs), for GNU/Linux 2.6.9, not stripped

$ cat /proc/23026/status | grep ^Vm
VmPeak:  4040288 kB
VmSize:  4040288 kB
VmLck:         0 kB
VmHWM:     13468 kB
VmRSS:     13468 kB
VmData:  4024800 kB
VmStk:        88 kB
VmExe:         4 kB
VmLib:     10044 kB
VmPTE:       112 kB

Jest tu kilka przydatnych wyników testów dla platform, których brakowało. Dobra praca z wykorzystaniem zrzutów plików i pamięci.
mikrofon

3

Powinno być dużo lepiej

W przypadku 32-bitowej maszyny JVM działającej na 64-bitowym hoście wyobrażam sobie, że to, co pozostanie na stercie, będzie dowolną niefragmentowaną przestrzenią wirtualną dostępną po JVM, jej własną biblioteką DLL i załadowaniem wszelkich elementów kompatybilności z 32-bitowym systemem operacyjnym. Wydaje mi się, że 3 GB powinno być możliwe, ale o ile lepiej to zależy od tego, jak dobrze sobie radzisz w 32-bitowym host-land.

Ponadto, nawet jeśli mógłbyś stworzyć gigantyczną stertę 3 GB, możesz nie chcieć, ponieważ spowoduje to, że przerwy w GC staną się potencjalnie kłopotliwe. Niektórzy ludzie po prostu uruchamiają więcej maszyn JVM, aby użyć dodatkowej pamięci zamiast jednej gigantycznej. Wyobrażam sobie, że właśnie teraz dostrajają maszyny JVM, aby działały lepiej z gigantycznymi stertami.

Trochę trudno jest dokładnie wiedzieć, o ile lepiej możesz zrobić. Domyślam się, że twoją 32-bitową sytuację można łatwo określić eksperymentalnie. Z pewnością trudno to przewidzieć abstrakcyjnie, ponieważ wiele rzeczy ma na to wpływ, szczególnie dlatego, że przestrzeń wirtualna dostępna na 32-bitowych hostach jest raczej ograniczona. Sterta musi istnieć w ciągłej pamięci wirtualnej, więc fragmentacja przestrzeni adresowej dla dll i wewnętrzne użycie przestrzeni adresowej przez jądro systemu operacyjnego określi zakres możliwych alokacji.

System operacyjny będzie wykorzystywał część przestrzeni adresowej do mapowania urządzeń sprzętowych i własnych dynamicznych alokacji. Chociaż ta pamięć nie jest mapowana na przestrzeń adresową procesu java, jądro systemu operacyjnego nie może jednocześnie uzyskać do niej dostępu i Twojej przestrzeni adresowej, więc ograniczy rozmiar przestrzeni wirtualnej dowolnego programu.

Ładowanie DLL zależy od implementacji i wydania maszyny JVM. Ładowanie jądra systemu operacyjnego zależy od ogromnej liczby rzeczy, wersji, sprzętu, liczby zmapowanych rzeczy do tej pory od ostatniego restartu, kto wie ...

W podsumowaniu

Założę się, że dostaniesz 1-2 GB w 32-bitowej ziemi i około 3 w 64-bitowej, więc ogólna poprawa wynosi około 2x .


1
Niestety nie mam do dyspozycji środowiska 64-bitowego, w którym mógłbym eksperymentować z flagą Xmx. Ten, o którym wiem, ma ogromną (32 * n) GB ilość dostępnej pamięci RAM, ale poza zakresem. Dlatego chciałem wiedzieć, jak 32-bitowa maszyna JVM działałaby bez wszystkich ograniczeń, z którymi normalnie się boryka w 32-bitowym świecie.
Vineet Reynolds

Cóż, dobre pytanie. Jestem pewien, że podstawowa odpowiedź brzmi: „będzie lepiej”.
DigitalRoss

Ok, zredagowałem moją odpowiedź, aby bardziej skupić się na Twoim rzeczywistym pytaniu. :-)
DigitalRoss

1
≅ 3 GB w 64-bitowych dźwiękach prawie w porządku. Thorbjørn już wskazał, dlaczego teoretycznie nie może przekraczać 4 GB. Szkoda, że ​​nie mogę przyjąć dwóch odpowiedzi.
Vineet Reynolds

Jeśli masz duże pudełko, możesz eksperymentować z 64-bitowym Solarisem np. W virtualbox (który ma najlepszą obsługę gości Solaris).
Thorbjørn Ravn Andersen

2

W Solarisie limit ten wynosił około 3,5 GB od wersji Solaris 2.5. (około 10 lat temu)


Mam zamiar poeksperymentować z tym, używając Oracle Solaris Express 11.
djangofan,

1
@Peter Lawrey Uhm .. Solaris 2.5 był prawie 20 lat temu, jeśli weźmie się pod uwagę datę premiery w maju 1996 ... oczywiście nie
wycofał się

1

Miałem te same problemy z maszyną JVM, z której korzysta App Inventor dla Android Blocks Editor. Ustawia pryzmę na maks. 925 m. To za mało, ale nie mogłem ustawić więcej niż około 1200m, w zależności od różnych czynników losowych na mojej maszynie.

Pobrałem Nightly, 64-bitową przeglądarkę beta z Firefoksa, a także 64-bitową wersję JAVA 7.

Nie znalazłem jeszcze mojego nowego limitu sterty, ale właśnie otworzyłem maszynę JVM o wielkości sterty 5900m . Nie ma problemu!

Używam Win 7 64 bit Ultimate na komputerze z 24 GB pamięci RAM.


0

Próbowałem ustawić rozmiar sterty do 2200M na 32-bitowej maszynie Linux i JVM działało dobrze. JVM nie uruchomił się, kiedy ustawiłem go na 2300M.


Pomyślałem, że dodam, że w 64-bitowym systemie Windows VISTA 32-bitowa JVM osiąga maksymalnie 1582 m (wartość -Xmx). Będzie narzekać, jeśli podam 1583m. Nie wiem, czy ta wartość zmienia się z maszyny na maszynę. Komputer, na którym to testowałem, faktycznie miał 4 GB fizycznej pamięci RAM.
Santosh Tiwari

@SantoshTiwari zmienia się z maszyny na maszynę, ale oto dlaczego
Eugene


0

jeszcze jeden punkt dla 32-bitowej JVM hotspot: - natywna pojemność sterty = 4 Gig - Java Heap - PermGen;

Może to być szczególnie trudne w przypadku 32-bitowej maszyny JVM, ponieważ Java Heap i natywny Heap są w wyścigu. Im większa sterta Java, tym mniejsza sterta natywna. Próba skonfigurowania dużej sterty dla 32-bitowej maszyny wirtualnej, np. 2,5 GB +, zwiększa ryzyko natywnego OutOfMemoryError w zależności od rozmiaru aplikacji, liczby wątków itp.


0

Ograniczenie wynika również z faktu, że w przypadku 32 bitmaszyny wirtualnej heapsama musi zaczynać się od adresu zero, jeśli chcesz to wszystko 4GB.

Pomyśl o tym, jeśli chcesz się do czegoś odwołać poprzez:

0000....0001

tj .: odniesienie, które ma tę konkretną reprezentację bitów, oznacza to, że próbujesz uzyskać dostęp do pierwszej pamięci ze sterty. Aby było to możliwe, sterta musi zaczynać się od adresu zero. Ale to się nigdy nie zdarza, zaczyna się z pewnym przesunięciem od zera:

    | ....               .... {heap_start .... heap_end} ... |
 --> (this can't be referenced) <--

Ponieważ sterta nigdy nie zaczyna się od adresu zerowego w an OS, jest sporo bitów, które nigdy nie są używane z 32odniesienia do bitów, a zatem sterta, do której można się odwołać, jest mniejsza.


-1

Teoretycznie 4 GB, ale w praktyce (dla IBM JVM):

Win 2k8 64, IBM Websphere Application Server 8.5.5 32bit

C:\IBM\WebSphere\AppServer\bin>managesdk.bat -listAvailable -verbose CWSDK1003I: Доступные SDK: CWSDK1005I: Имя SDK: 1.6_32 - com.ibm.websphere.sdk.version.1.6_32=1.6 - com.ibm.websphere.sdk.bits.1.6_32=32 - com.ibm.websphere.sdk.location.1.6_32=${WAS_INSTALL_ROOT}/java - com.ibm.websphere.sdk.platform.1.6_32=windows - com.ibm.websphere.sdk.architecture.1.6_32=x86_32 - com.ibm.websphere.sdk.nativeLibPath.1.6_32=${WAS_INSTALL_ROOT}/lib/native/win /x86_32/ CWSDK1001I: Задача managesdk выполнена успешно. C:\IBM\WebSphere\AppServer\java\bin>java -Xmx2036 MaxMemory JVMJ9GC017E -Xmx слишком мала, должна быть не меньше 1 M байт JVMJ9VM015W Ошибка инициализации для библиотеки j9gc26(2): Не удалось инициализи ровать Could not create the Java virtual machine. C:\IBM\WebSphere\AppServer\java\bin>java -Xmx2047M MaxMemory Total Memory: 4194304 (4.0 MiB) Max Memory: 2146435072 (2047.0 MiB) Free Memory: 3064536 (2.9225692749023438 MiB) C:\IBM\WebSphere\AppServer\java\bin>java -Xmx2048M MaxMemory JVMJ9VM015W Ошибка инициализации для библиотеки j9gc26(2): Не удалось создать эк земпляр кучи; запрошено 2G Could not create the Java virtual machine.

RHEL 6.4 64, IBM Websphere Application Server 8.5.5 32-bitowy

[bin]./java -Xmx3791M MaxMemory Total Memory: 4194304 (4.0 MiB) Max Memory: 3975151616 (3791.0 MiB) Free Memory: 3232992 (3.083221435546875 MiB) [root@nagios1p bin]# ./java -Xmx3793M MaxMemory Total Memory: 4194304 (4.0 MiB) Max Memory: 3977248768 (3793.0 MiB) Free Memory: 3232992 (3.083221435546875 MiB) [bin]# /opt/IBM/WebSphere/AppServer/bin/managesdk.sh -listAvailable -verbose CWSDK1003I: Available SDKs : CWSDK1005I: SDK name: 1.6_32 - com.ibm.websphere.sdk.version.1.6_32=1.6 - com.ibm.websphere.sdk.bits.1.6_32=32 - com.ibm.websphere.sdk.location.1.6_32=${WAS_INSTALL_ROOT}/java - com.ibm.websphere.sdk.platform.1.6_32=linux - com.ibm.websphere.sdk.architecture.1.6_32=x86_32 -com.ibm.websphere.sdk.nativeLibPath.1.6_32=${WAS_INSTALL_ROOT}/lib/native/linux/x86_32/ CWSDK1001I: Successfully performed the requested managesdk task.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.