Kann mir jemand erklären, warum JVMs (ich habe nicht zu viele geprüft, aber ich habe noch nie eine gesehen, die das nicht so gemacht hat) auf einer festen Heap-Größe ausgeführt werden müssen? Ich weiß, dass die Implementierung auf einem einfachen zusammenhängenden Heap einfacher ist, aber die Sun-JVM ist inzwischen über ein Jahrzehnt alt, und ich würde davon ausgehen, dass sie Zeit hatten, dies zu verbessern.
Die Notwendigkeit, die maximale Speichergröße Ihres Programms zum Startzeitpunkt zu definieren, scheint in den 1960er Jahren ein Problem zu sein, und dann gibt es die schlechten Wechselwirkungen mit der virtuellen Speicherverwaltung des Betriebssystems (GC-Abruf von ausgelagerten Daten, Unfähigkeit zu bestimmen, wie viel Speicher der Java-Prozess ist) wirklich mit von der OS - Seite, verschwendet große Mengen an VM Raum (ich weiß, kümmert es dich nicht auf deine Phantasie 48bit Maschinen ...)). Ich vermute auch, dass die verschiedenen traurigen Versuche, kleine Betriebssysteme innerhalb der JVM (EE Application Server, OSGi) zu erstellen, zumindest teilweise auf diesen Umstand zurückzuführen sind, da das Ausführen mehrerer Java-Prozesse auf einem System ausnahmslos zu Ressourcenverschwendung führt, da dies erforderlich ist Geben Sie jedem Speicher den Speicher an, den er zu Spitzenzeiten verwenden muss.
Überraschenderweise hat Google darüber nicht die erwarteten Empörungsstürme ausgelöst, aber sie wurden möglicherweise unter den Millionen von Menschen begraben, die sich über eine feste Haufengröße informierten und diese Tatsache einfach akzeptierten.
Antworten:
Sie liegen falsch. Die Größe des Heapspeichers von JVMs ist nicht festgelegt, sondern nur begrenzt:
Das Festlegen einer Obergrenze ist aus mehreren Gründen erforderlich. Erstens teilt es dem Müllmann mit, wann er in Aktion treten soll. Zweitens wird verhindert, dass die JVM die gesamte Maschine verstopft, indem zu viel Speicher verbraucht wird. Die minimale Größe des Heapspeichers ist wahrscheinlich nützlich, um die Menge an Speicher zu reservieren, die das Programm mindestens benötigt, um zu verhindern, dass ihm der Speicher ausgeht (weil andere Prozesse zu viel Speicher verbrauchen).
quelle
Ich stelle mir vor, die Antwort hat etwas mit Javas Erbe zu tun. Es wurde ursprünglich als Sprache für eingebettete Systeme entwickelt, bei denen die Ressourcen offensichtlich begrenzt sind und Prozesse nicht einfach das verschlingen sollen, was verfügbar ist. Dies hilft auch bei der Systemadministration, da es einfacher ist, Ressourcen auf einem Server bereitzustellen, wenn Sie Ressourcenlimits festlegen können. Ich sehe, dass die neuesten JVMs anscheinend mehrere nicht fortlaufende Heaps verwenden, obwohl natürlich alles als ein einziger Heap für Ihren Code angezeigt wird.
(FWIW, Sie mussten den Speicherbedarf eines Programms unter den MacOS-Versionen vor Darwin von Apple angeben [bis auf System 7, das das letzte war, das ich verwendet habe], das bis weit in die 80er Jahre reicht.)
quelle
Sie müssen dem GC einen Mechanismus geben, der angibt , wann er ausgeführt werden soll. Andernfalls füllt Ihr Programm den gesamten virtuellen Speicherplatz aus. Es gibt viele alternative Möglichkeiten, um GC auszulösen: verstrichene Zeit, Anzahl der Zuweisungen, Anzahl der Zuweisungen, wahrscheinlich andere, die mir derzeit nicht einfallen. IMO ist keines davon so gut wie das Festlegen einer Speichergrenze und das Ausführen von GC, wenn der zugewiesene Speicherplatz diese Grenze erreicht.
Der Schlüssel ist, die richtigen Grenzen zu setzen. Ich betrachte
-ms
als "das ist, wie viel Speicher meine App benötigt", und-mx
als "es sollte nie diese Menge überschreiten." In einer Produktionsbereitstellung sollten beide nahe beieinander liegen, wenn sie nicht gleich sind, und sie sollten auf tatsächlichen, gemessenen Anforderungen basieren.Ihre Bedenken hinsichtlich "verschwendeten" virtuellen Speichers sind falsch platziert: Es ist virtuell, es ist (fast) kostenlos. Ja, wenn der Heap zu groß ist, können Sie nicht so viele Threads starten oder so viele Dateien mit Speicherzuordnung laden. Dies ist jedoch Teil des Anwendungsdesigns: Sie haben knappe Ressourcen und müssen diese so partitionieren, dass Ihre Anwendung ausgeführt werden kann. In einem Heap im C-Stil, der sich ausdehnt, bis Sie die Speicherkapazität erreicht haben, ist das Grundproblem dasselbe. Sie müssen nur nicht darüber nachdenken, bis Sie in Schwierigkeiten sind.
Das einzige, was ein großer Heap "verschwenden" könnte, ist der Swap-Speicher, da für alle beschreibbaren Segmente ein Commit von Swap erforderlich ist. Dies ist jedoch Teil des Systemdesigns: Wenn Sie möchten, dass viele JVMs auf derselben Box ausgeführt werden, erhöhen Sie entweder Ihren Swap, oder verringern Sie die Heap-Zuweisung. Wenn sie zu krachen beginnen, versuchen Sie, zu viel mit dem System zu tun. Kaufen Sie mehr Speicher (und wenn Sie noch einen 32-Bit-Prozessor verwenden, kaufen Sie eine neue Box).
quelle
Wie sagt user281377 geben Sie nur eine Obergrenze, wie viel Speicher Ihr Prozess kann verbrauchen. Natürlich greift die Anwendung selbst nur auf den benötigten Speicherplatz zu.
Ob es eine Standardobergrenze geben sollte oder nicht, ist eine andere Frage, sowohl für als auch gegen.
quelle