2008-09-16 8 views
1

Ich habe ein spezielles Problem mit bestimmten Java-Anwendungen in der HP-UX-Umgebung festgestellt.Was läuft in einem C-Heap und einem Java-Heap in HP-UX-Umgebungs-JVMs?

Der Heap wird auf -mx512 gesetzt, doch wenn man sich die Speicherbereiche für diesen Java-Prozess mit gpm anschaut, zeigt dies, dass mehr als 1,6 GB RSS-Speicher verwendet werden und 1,1 GB der DATA-Region zugewiesen sind. Wächst ziemlich schnell über einen Zeitraum von 24-48 Stunden und verlangsamt sich dann wesentlich, wächst immer noch 2 MB alle paar Stunden. Der Java-Heap zeigt jedoch keine Anzeichen von Lecks.

Neugierig, wie dies möglich war ich ein bisschen recherchiert und fand diese HP Zuschreibung auf Speicherlecks in Java Heap und c Haufen: http://docs.hp.com/en/JAVAPERFTUNE/Memory-Management.pdf

Meine Frage ist, was bestimmt, was in dem C-Heap vs der Java-RAN Heap, und für Dinge, die nicht durch den Java-Heap laufen, wie würden Sie diejenigen Objekte identifizieren, die auf dem C-Heap laufen? Zusätzlich sitzt der Java-Heap innerhalb des C-Heaps?

Antwort

0

Meine einzige Schätzung mit den Zahlen, die Sie angegeben haben, ist ein Speicherleck in der Java VM. Vielleicht möchten Sie eine der anderen VMs versuchen, die sie in dem von Ihnen genannten Papier aufgeführt haben. Eine andere (viel schwierigere) Alternative könnte das Kompilieren des offenen Java auf der HP-Plattform sein.

Suns Java ist noch nicht 100% offen, sie arbeiten daran, aber ich glaube, dass es in sourceforge einen gibt.

Java verdrängt übrigens auch Speicher. Manchmal verwechselt es die Speicherverwaltung des Betriebssystems ein wenig (Sie sehen es, wenn Windows nicht mehr genügend Speicher hat und Java bittet, einige davon freizugeben, Java berührt alle seine Objekte, was dazu führt, dass sie aus der Auslagerungsdatei geladen werden, Windows schreit qualvoll und stirbt), aber Ich glaube nicht, dass du das siehst.

2

Im Allgemeinen werden nur die Daten in Java-Objekten auf dem Java-Heap gespeichert, der gesamte von der Java-VM benötigte Speicher wird vom "nativen" oder "C" -Haufen zugewiesen (tatsächlich ist der Java-Heap selbst einfach) ein zusammenhängender Chunk, der vom C-Heap zugewiesen wurde).

Da die JVM den Java-Heap (oder Heaps, wenn generationale Speicherbereinigung verwendet wird) als zusammenhängenden Speicherabschnitt benötigt, wird die gesamte maximale Heapgröße (-mx-Wert) normalerweise zur JVM-Startzeit zugewiesen. In der Praxis wird die Java-VM versuchen, diesen Speicherplatz so gering wie möglich zu halten, so dass das Betriebssystem keinen realen Speicher reservieren muss (das Betriebssystem ist clever genug, um zu wissen, wann auf ein Speichermedium noch nie geschrieben wurde) .

Der Java-Heap belegt daher einen gewissen Speicherplatz im Speicher.

Der Rest des Speichers wird von der Java-VM und jedem verwendeten JNI-Code verwendet. Zum Beispiel benötigt die JVM Speicher zum Speichern von Java-Bytecode- und Konstantenpools aus geladenen Klassen, das Ergebnis von JIT-kompiliertem Code, Arbeitsbereiche zum Kompilieren von JIT-Code, native Thread-Stapel und andere derartige Kleinigkeiten.

JNI-Code ist nur plattformspezifischer (kompilierter) C-Code, der in Form einer "nativen" Methode an ein Java-Objekt gebunden werden kann. Wenn diese Methode ausgeführt wird, wird der gebundene Code ausgeführt und kann Speicher unter Verwendung von Standard-C-Routinen (z. B. malloc) zuordnen, die Speicher auf dem C-Heap verbrauchen.

4

Überlegen Sie, was einen Java-Prozess ausmacht.

Sie haben:

  • die JVM (ein C-Programm)
  • JNI Daten
  • Java Bytecode
  • Java Daten

Bemerkenswert ist, sie alle leben in der C Heap (der JVM-Heap ist natürlich ein Teil des C-Heaps).

Im Java-Heap sind einfach Java-Byte-Codes und die Java-Daten. Was aber auch im Java-Heap ist, ist "freier Speicherplatz".

Die typische (d. H. Sun) JVM wächst nur Java Heap wie nötig, verkleinert sie aber nie. Sobald es sein definiertes Maximum erreicht (-Xmx512M), hört es auf zu wachsen und behandelt alles, was noch übrig ist. Wenn dieser maximale Heap erschöpft ist, erhalten Sie die OutOfMemory-Ausnahme.

Was diese Xmx512M Option NICHT tut, ist die Gesamtgröße des Prozesses zu begrenzen. Es beschränkt nur den Java-Heap-Teil des Prozesses.

Zum Beispiel könnten Sie ein künstliches Java-Programm haben, das 10 MB Java Heap verwendet, aber einen JNI-Aufruf aufruft, der 500 MB C Heap zuweist. Sie können sehen, wie groß die Prozessgröße ist, obwohl der Java-Heap klein ist. Mit den neuen NIO-Bibliotheken können Sie auch Speicher außerhalb des Heapspeichers anhängen.

Der andere Aspekt, den Sie berücksichtigen müssen, ist, dass der Java GC normalerweise ein "Copying Collector" ist. Das bedeutet, dass es die "Live" -Daten aus dem Speicher, den es sammelt, benötigt, und es in einen anderen Speicherabschnitt kopiert. Dieser leere Platz, der kopiert wird, ist NICHT TEIL DES HEAPS, zumindest nicht in Bezug auf den Xmx-Parameter. Es ist wie "der neue Heap" und wird nach der Kopie Teil des Heaps (der alte Space wird für den nächsten GC verwendet). Wenn Sie über einen 512-MB-Heapspeicher mit 510 MB verfügen, kopiert Java die Live-Daten an einen anderen Speicherort. Der naive Gedanke wäre zu einem anderen großen offenen Raum (wie 500 + MB). Wenn alle Ihre Daten "live" wären, dann würde es einen großen Brocken wie diesen brauchen, um hineinkopieren zu können.

So können Sie sehen, dass Sie in den extremsten Rand Fällen mindestens doppelt so viel freien Speicher auf Ihrem System benötigen, um eine bestimmte Heap-Größe zu behandeln. Mindestens 1 GB für einen 512 MB großen Heap.

Es stellt sich heraus, dass nicht der Fall in der Praxis und Speicherzuordnung und solche ist komplizierter als das, aber Sie benötigen einen großen Teil des freien Speichers, um die Heap-Kopien zu behandeln, und dies wirkt sich auf die Gesamtprozessgröße.

Schließlich ist zu beachten, dass die JVM Dinge wie mapping in den rt.jar-Klassen in der VM Spaß macht, um den Start zu erleichtern. Sie sind in einem schreibgeschützten Block zugeordnet und können für andere Java-Prozesse freigegeben werden. Diese geteilten Seiten werden gegen alle Java-Prozesse "gezählt", obwohl sie wirklich nur einmal physischen Speicher verbrauchen (die Magie des virtuellen Speichers).

Nun, warum Ihr Prozess weiter wächst, wenn Sie niemals die Java OOM-Nachricht treffen, bedeutet dies, dass Ihr Leck NICHT im Java-Heap ist, aber das bedeutet nicht, dass es sich nicht in etwas anderem befindet JRE-Laufzeit, eine JNI-Bibliothek von Drittanbietern, ein nativer JDBC-Treiber usw.).