Java maximaler Speicher unter Windows XP

103

Ich war immer in der Lage, Java SE unter 32-Bit-Windows XP (Java 1.4, 1.5 und 1.6) 1400 Megabyte zuzuweisen.

java -Xmx1400m ...

Heute habe ich die gleiche Option auf einem neuen Windows XP-Computer mit Java 1.5_16 und 1.6.0_07 ausprobiert und den Fehler erhalten:

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

Durch Versuch und Irrtum scheint es, dass 1200 Megabyte das Beste sind, was ich auf diesem Computer zuweisen kann.

Irgendwelche Ideen, warum eine Maschine 1400 und eine andere nur 1200 erlauben würde?

Bearbeiten: Der Computer verfügt über 4 GB RAM mit ca. 3,5 GB, die Windows erkennen kann.

Steve Kuo
quelle
Sie würden einen Unterschied im Maximum zwischen dem Ausführen der App in einer 32-Bit-Shell oder einer 64-Bit-Shell feststellen, zumindest nach meiner Erfahrung, obwohl 64-Bit-WindowsXP-Systeme selten sind.
Djangofan

Antworten:

124

Beachten Sie, dass Windows über eine virtuelle Speicherverwaltung verfügt und die JVM nur Speicher benötigt, der in seinem Adressraum zusammenhängend ist . Andere Programme, die auf dem System ausgeführt werden, sollten sich also nicht unbedingt auf Ihre Heap-Größe auswirken. Was Ihnen im Weg steht, sind DLLs, die in Ihren Adressraum geladen werden. Leider erhöhen Optimierungen in Windows, die die Verlagerung von DLLs während der Verknüpfung minimieren, die Wahrscheinlichkeit, dass Sie einen fragmentierten Adressraum haben. Zu den Dingen, die neben den üblichen Dingen wahrscheinlich in Ihren Adressraum eingreifen, gehören Sicherheitssoftware, CBT-Software, Spyware und andere Formen von Malware. Mögliche Ursachen für die Abweichungen sind unterschiedliche Sicherheitspatches, C-Laufzeitversionen usw. Gerätetreiber und andere Kernelbits haben einen eigenen Adressraum (die anderen 2 GB des 4 GB 32-Bit-Raums).

Sie können versuchen, Ihre DLL-Bindungen in Ihrem JVM-Prozess durchzugehen und zu versuchen, Ihre DLLs in einen kompakteren Adressraum umzuwandeln. Kein Spaß, aber wenn Sie verzweifelt sind ...

Alternativ können Sie einfach zu 64-Bit-Windows und einer 64-Bit-JVM wechseln. Ungeachtet dessen, was andere vorgeschlagen haben, wird zwar mehr RAM verbraucht, Sie haben jedoch einen viel zusammenhängenderen virtuellen Adressraum, und die Zuweisung von 2 GB zusammenhängend wäre trivial.

Christopher Smith
quelle
5
Verwenden Sie den Prozess-Explorer, um zu sehen, wo im Speicher DLLs geladen werden. Oft bleibt ein aktualisierter Treiber in der Mitte Ihres Adressraums hängen. Mit dem Befehl REBASE können Sie diese einfach aus dem Weg schieben. Beachten Sie jedoch, dass die DLL erneut aktualisiert werden und Probleme verursachen muss.
Brianegge
2
Ich habe dies nie als Antwort akzeptiert und dennoch hat der Stapelüberlauf es als beantwortet markiert.
Steve Kuo
@Christopher, Ist es möglich, 64-Bit-JVM unter 32-Bit-Windows XP zu verwenden?
Pacerier
@ Pacerier Entschuldigung, ich habe Ihre Anfrage verpasst. AFAIK, das ist nicht möglich. OS X hatte einige Tricks für den 64-Bit-Benutzerbereich mit 32-Bit-Kerneln, aber ich habe noch nichts davon für Windows gehört.
Christopher Smith
@ChristopherSmith, Übrigens, Sie haben erwähnt, dass " andere Programme, die auf dem System ausgeführt werden, nicht unbedingt Ihre Heap-Größe beeinflussen sollten ". Wenn ja, wie erklären wir dieses Ergebnis: stackoverflow.com/questions/9303889/… ?
Pacerier
50

Dies hat mit zusammenhängendem Speicher zu tun.

Hier sind einige Informationen, die ich online für jemanden gefunden habe, der das zuvor gefragt hat, angeblich von einem "VM-Gott":

Der Grund, warum wir einen zusammenhängenden Speicherbereich für den Heap benötigen, besteht darin, dass wir eine Reihe von Seitendatenstrukturen haben, die vom Beginn des Heaps an durch (skalierte) Offsets indiziert werden. Beispielsweise verfolgen wir Objektreferenzaktualisierungen mit einem "Kartenmarkierungsarray", das ein Byte für jeweils 512 Byte Heap enthält. Wenn wir eine Referenz im Heap speichern, müssen wir das entsprechende Byte im Kartenmarkierungsarray markieren. Wir verschieben die Zieladresse des Geschäfts nach rechts und indizieren damit das Kartenmarkierungsarray. Es macht Spaß, sich mit arithmetischen Spielen zu befassen, die Sie in Java nicht können und die Sie in C ++ spielen müssen (müssen :-).

Normalerweise haben wir keine Probleme, bescheidene zusammenhängende Regionen zu erhalten (bis zu 1,5 GB bei Windohs, bis zu 3,8 GB bei Solaris. YMMV.). Unter Windohs besteht das Problem hauptsächlich darin, dass vor dem Start der JVM einige Bibliotheken geladen werden, die den Adressraum aufteilen. Wenn Sie den Schalter / 3GB verwenden, werden diese Bibliotheken nicht neu gestartet, sodass sie für uns immer noch ein Problem darstellen.

Wir wissen, wie man zerhackte Haufen macht, aber es würde einen gewissen Aufwand bedeuten, sie zu verwenden. Wir haben mehr Anforderungen an eine schnellere Speicherverwaltung als an größere Heaps in der 32-Bit-JVM. Wenn Sie wirklich große Haufen wollen, wechseln Sie zur 64-Bit-JVM. Wir brauchen noch zusammenhängenden Speicher, aber es ist viel einfacher, in einen 64-Bit-Adressraum zu gelangen.

Uri
quelle
Das ist sehr interessant. Ich habe mich immer gefragt, warum 1500 MB, jetzt habe ich es bekommen, danke!
Tim Büthe
3
Es tut mir leid, dass ich eine uralte Frage beantwortet habe, aber dies ist die beste Antwort, die ich bisher gesehen habe. Aber warum schlägt die JVM beim Start fehl, wenn sie nicht die maximale Heap-Größe erreichen kann? Sollte es sich nicht ruhig mit der besten Größe über dem Minimum zufrieden geben ?
Stroboskop
19

Die Java-Heap-Größenbeschränkungen für Windows sind:

  • Maximal mögliche Heap-Größe unter 32-Bit-Java: 1,8 GB
  • Empfohlene Heap-Größenbeschränkung für 32-Bit-Java: 1,5 GB (oder 1,8 GB mit / 3 GB- Option)

Dies hilft Ihnen nicht dabei, einen größeren Java-Heap zu erhalten, aber jetzt wissen Sie, dass Sie diese Werte nicht überschreiten können.

MicSim
quelle
10

Oracle JRockit , das einen nicht zusammenhängenden Heap verarbeiten kann, kann unter Windows 2003 / XP mit dem Schalter / 3 GB eine Java-Heap-Größe von 2,85 GB haben. Es scheint, dass die Fragmentierung einen erheblichen Einfluss darauf haben kann, wie groß ein Java-Heap sein kann.

Kire Haglin
quelle
6

Die JVM benötigt zusammenhängenden Speicher. Je nachdem, was noch ausgeführt wird, was zuvor ausgeführt wurde und wie Windows den Speicher verwaltet hat, können Sie möglicherweise bis zu 1,4 GB zusammenhängenden Speicher abrufen. Ich denke, 64-Bit-Windows wird größere Haufen erlauben.

James AN Stauffer
quelle
2
Ich denke, moderne Betriebssysteme emulieren kontinuierlichen Speicher für die. Seit dem 80486 unterstützt die x86-Architektur Paging, um die Neuanordnung des physischen Speichers zu vereinfachen.
Mnementh
3
Mnemeth: Erstens gibt es in WINAPI eine spezielle API (AllocateUserPhysicalPages) für erweiterte Tools wie Datenbanken und VMs, die besser in der Lage sind, ihren Speicher selbst mit Windows zu verwalten. Zweitens ist Paging eine Funktion im geschützten 80386-Modus, nicht 80486.
Tamas Czinege
6

Die JVM von Sun benötigt zusammenhängenden Speicher. Die maximale Menge an verfügbarem Speicher wird also durch die Speicherfragmentierung bestimmt. Insbesondere DLLs des Treibers neigen dazu, den Speicher zu fragmentieren, wenn sie in eine vordefinierte Basisadresse geladen werden. Ihre Hardware und ihre Treiber bestimmen also, wie viel Speicher Sie erhalten können.

Zwei Quellen dafür mit Aussagen von Sun-Ingenieuren: Forum- Blog

Vielleicht noch eine JVM? Haben Sie Harmony ausprobiert ? Ich denke, sie wollten ein nicht kontinuierliches Gedächtnis zulassen.

the.duckman
quelle
Aber ich konnte 1300 MB auf einem Computer mit nur 1 GB RAM (plus virtuellem Speicher) zuweisen. Mein 2 GB RAM-Computer (auch mit virtuellem Speicher) kann nur 1200 MB zuweisen.
Steve Kuo
Harmonie ist tot, nicht wahr?
Pacerier
Ja: "Apache Harmony ist seit dem 16. November 2011 bei der Apache Software Foundation im Ruhestand."
Bobbel
3

Ich denke, es hat mehr damit zu tun, wie Windows konfiguriert ist, wie in dieser Antwort angedeutet: Java -Xmx Option

Weitere Tests: Ich konnte 1300 MB auf einem alten Windows XP-Computer mit nur 768 MB physischem RAM (plus virtuellem Speicher) zuweisen. Auf meinem 2 GB RAM-Computer kann ich nur 1220 MB bekommen. Auf verschiedenen anderen Unternehmenscomputern (mit älterem Windows XP) konnte ich 1400 MB erhalten. Der Computer mit einem Limit von 1220 MB ist ziemlich neu (gerade von Dell gekauft), daher verfügt er möglicherweise über neuere (und aufgeblähte) Windows- und DLLs (es wird Windows XP Pro Version 2002 SP2 ausgeführt).

Steve Kuo
quelle
Dies kann auch durch Ihre Einstellungen für den virtuellen Speicher beeinflusst werden.
Skaffman
Alle Maschinen, mit denen ich teste, verfügen über einen virtuellen Speicher, der mindestens doppelt so groß ist wie der physische RAM.
Steve Kuo
Beachten Sie, dass Sie den virtuellen Speicher mit Java wirklich nie wirklich verwenden möchten, da die GC-Leistung sehr schlecht wird. Die Speichermenge hängt davon ab, welche DLLs bereits geladen und den Speicher fragmentiert wurden.
Kohlerm
2

Ich habe diese Fehlermeldung erhalten, wenn ich ein Java-Programm von einem (begrenzten Speicher) virtuozzo VPS ausgeführt habe. Ich hatte keine Speicherargumente angegeben und musste explizit ein kleines festlegen Betrag da der Standardwert zu hoch gewesen sein muss. ZB -Xmx32m (muss natürlich je nach ausgeführtem Programm angepasst werden).

Setzen Sie dies hier ein, falls jemand anderes die obige Fehlermeldung erhält, ohne eine große Speichermenge anzugeben, wie es der Fragesteller getan hat.

William Denniss
quelle
1

Das JDK / JRE von sun benötigt eine zusammenhängende Speichermenge, wenn Sie einen großen Block zuweisen.

Das Betriebssystem und die ersten Apps neigen dazu, beim Laden Teile zuzuweisen, wodurch der verfügbare RAM fragmentiert wird. Wenn ein zusammenhängender Block NICHT verfügbar ist, kann das SUN JDK ihn nicht verwenden. JRockit von Bea (von Oracle erworben) kann Speicher aus Teilen zuweisen.

anjanb
quelle
1

Jeder scheint über zusammenhängende Erinnerungen zu antworten, hat es jedoch versäumt, ein dringlicheres Problem anzuerkennen.

Selbst bei einer zu 100% zusammenhängenden Speicherzuweisung können Sie unter einem 32-Bit-Windows-Betriebssystem (standardmäßig *) keine Heap-Größe von 2 GiB haben. Dies liegt daran, dass 32-Bit-Windows-Prozesse nicht mehr als 2 GB Speicherplatz adressieren können.

Der Java-Prozess enthält neben dem Heap auch Perm-Gen (vor Java 8), Stapelgröße pro Thread, JVM- / Bibliotheks-Overhead (der sich mit jedem Build erheblich erhöht) .

Darüber hinaus ändern sich die JVM-Flags und ihre Standardwerte zwischen den Versionen. Führen Sie einfach Folgendes aus und Sie erhalten eine Vorstellung:

 java -XX:+PrintFlagsFinal

Viele der Optionen wirken sich auf die Speicheraufteilung in und aus dem Heap aus. Sie haben mehr oder weniger von diesen 2 GiB zum Spielen ...

Zur Wiederverwendung Portionen dieser Antwort von mir (etwa Tomcat, sondern gilt für alle Java - Prozess):

Das Windows-Betriebssystem begrenzt die Speicherzuweisung eines 32-Bit-Prozesses auf insgesamt 2 GB (standardmäßig).

[Sie können nur] ca. 1,5 GB Heap-Speicherplatz zuweisen, da dem Prozess auch anderer Speicher zugewiesen ist (JVM- / Bibliotheks-Overhead, Dauerwellen-Speicherplatz usw.).

Warum legt 32-Bit-Windows eine Prozessadressraumbeschränkung von 2 GB fest, 64-Bit-Windows jedoch eine Beschränkung von 4 GB?

Andere moderne Betriebssysteme [Husten Linux] ermöglichen es 32-Bit-Prozessen, den gesamten (oder den größten Teil) des adressierbaren 4-GiB-Raums zu nutzen.

Das heißt, 64-Bit-Windows-Betriebssysteme können so konfiguriert werden, dass das Limit von 32-Bit-Prozessen auf 4 GiB (3 GiB auf 32-Bit) erhöht wird:

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

Michael
quelle
1
Diese Antwort spricht nur an, warum er möglicherweise nur 2 GB zuweisen kann, nicht, warum er 1,4 GB auf einem Computer und nur 1,2 GB auf einem anderen Computer zuweisen kann. Er hat weder die hier angegebenen Grenzwerte von 1,5 GB, 2 GB noch 4 GB erreicht.
Vapcguy
1
Der Absatz über JVM-Flags erklärt in gewisser Weise, warum der Speicher zwischen den Versionen variieren kann. Beachten Sie auch meinen Punkt, dass die Heap-Einstellung immer einen (großen) Bruchteil der gesamten Prozessgröße ausmacht. Eine Einstellung darunter, die möglicherweise immer noch die Prozessgrenze von 2 GiB erreicht, kann durch die zusammenhängende Speicherzuweisung eingeschränkt werden.
Michael
Oder möglicherweise das 1,5-GB-Limit für die 1,4-GB-Zuweisung, die er vornimmt. Macht jetzt mehr Sinn - danke für diese Klarstellung.
Vapcguy
0

Hier erfahren Sie, wie Sie die Paging-Größe erhöhen

  1. Klicken Sie mit der rechten Maustaste auf mycomputer ---> Eigenschaften ---> Erweitert
  2. Klicken Sie im Abschnitt Leistung auf Einstellungen
  3. Klicken Sie auf die Registerkarte Erweitert
  4. Klicken Sie im Abschnitt Virtueller Speicher auf Ändern. Es wird Ihre aktuelle Paging-Größe angezeigt.
  5. Wählen Sie Laufwerk, auf dem Festplattenspeicher verfügbar ist.
  6. Geben Sie die Anfangsgröße und die maximale Größe an ... z. B. die anfängliche Größe 0 MB und die maximale Größe 4000 MB. (So ​​viel Sie benötigen)
Israel Margulies
quelle
0

** Es gibt zahlreiche Möglichkeiten, die Größe des Heapspeichers zu ändern, z.

  1. Datei-> Einstellung-> Erstellen, Ausführen, Bereitstellen-> Compiler Hier finden Sie die Heap-Größe
  2. Datei-> Einstellung-> Erstellen, Ausführen, Bereitstellen-> Compiler-> Andriod Hier finden Sie auch die Heap-Größe. Sie können dies für ein andriod-Projekt verwenden, wenn Sie mit demselben Problem konfrontiert sind.

Was für mich funktioniert hat war

  1. Stellen Sie den richtigen JAVA_HOME-Pfad ein, falls Java aktualisiert wurde.

  2. Neue Systemvariable erstellen Computer-> Eigenschaften-> Erweiterte Einstellungen- > Neue Systemvariable erstellen

Name: _JAVA_OPTION Wert: -Xmx750m

Zu Ihrer Information : Sie finden die Standard-VMoption in der Intellij- Hilfe-> benutzerdefinierte VM-Option bearbeiten . In dieser Datei sehen Sie die minimale und maximale Größe des Heapspeichers. **

Akanksha Gore
quelle
-1

Erstens ist die Verwendung einer Auslagerungsdatei bei 4 GB RAM nutzlos. Windows kann nicht auf mehr als 4 GB zugreifen (tatsächlich weniger aufgrund von Speicherlücken), sodass die Auslagerungsdatei nicht verwendet wird.

Zweitens wird der Adressraum in 2 geteilt, die Hälfte für den Kernel und die Hälfte für den Benutzermodus. Wenn Sie mehr RAM für Ihre Anwendungen benötigen, verwenden Sie die Option / 3GB in der Datei boot.ini (stellen Sie sicher, dass java.exe als "große Adresse bekannt" markiert ist (Google für weitere Informationen).

Drittens können Sie nicht die vollen 2 GB Adressraum zuweisen, da Java intern etwas Speicher verschwendet (für Threads, JIT-Compiler, VM-Initialisierung usw.). Verwenden Sie den Schalter / 3GB für mehr.

user17544
quelle
1
Die Vorstellung, dass eine Auslagerungsdatei mit 4 GB oder RAM unbrauchbar ist, ist falsch. Ohne eine Auslagerungsdatei kann das Betriebssystem nicht verwendete Prozessdaten (Stapelspeicher für nicht verwendete Dienste usw.) nicht aus dem physischen RAM entfernen, wodurch die für echte Arbeit verfügbare RAM-Größe verringert wird. Durch eine Auslagerungsdatei wird RAM freigegeben.
niemand