Garbage Collector in NetBeans vs. exe Anwendung

AlgoFX90

Mitglied
Hallo,

ich habe schon ein wenig in den Beiträgen gesucht, leider nichts konkret passendes gefunden.

Ich habe eine Anwendung geschrieben, welche Optimierungen durchführt(Programm läuft bis zu mehrere Stunden/ rechenintensiv).
Mein Problem ist nun, dass der Garbage Collector zwar in NetBeans funktioniert, d.h. Heap Size bleibt konstant bei ca. 200 MB und die Used HeapSize wird bereinigt,
allerdings wenn ich das Programm in einer Exe Anwendung starte, funktioniert die Bereinigung nicht. Die Heap Size & Used Heap Size steigt kontinuierlich an, bis irgendwann die Maximale Heap Size von 1024MB erreicht ist.
Natürlich verlangsamt sich die Anwendung durchgehend mit der Zeit.
Ich habe schon im Profiler nach Fehlern gesucht, allerdings kann dies wohl nicht
die Lösung sein, da es auch in NetBeans funktioniert.

Meine Frage: Wie schaffe ich es, dass meine Java Applikation den Speicher bereinigt, wie es anscheinend NetBeans automatisch macht. (System.gc verwende ich meinem Code an vielen Stellen, allerdings ohne Erfolg). Gibt es dort eine simple und schnelle Lösung?
(z.B per Console den Heap der JVM bereinigen und dies als exec im Code einbauen?)

Eine praktisch hilfreiche Antwort wäre sehr toll,
Gruß
 
Moin,

ich kenne NetBeans zwar nicht, glaube aber kaum, dass das Garbage Collection dort wesentlich anders funktioniert!

System.gc verwende ich meinem Code an vielen Stellen, allerdings ohne Erfolg
Das ist auch ziemlich sinnlos und sollte eigentlich vermieden werden!
Der händische Aufruf ist bestenfalls eine Empfehlung an den GC, doch mal aufzuräumen, mehr nicht.
Wenn nicht geht (sei es aus laufzeittechnischen Gründen oder weil betroffene Objekte noch Referenzen aufweisen), wird auch nichts passieren !

http://stackoverflow.com/questions/2414105/why-is-it-bad-practice-to-call-system-gc
https://blog.codecentric.de/2010/08/system-gc-aufrufe-konnen-schwere-folgen-haben/

EDIT: vermutlich ist das Laufzeitverhalten ein anderes - aus der Ferne schwer zu beurteilen !

Gruß Klaus
 
System.gc verwende ich meinem Code an vielen Stellen, allerdings ohne Erfolg

System.gc führt in den meisten Fällen zu schlechterem Laufzeitverhalten.

Grob gesagt gilt für Java (und generell) weniger Speicher = schlechtere Laufzeit. Der GC läuft dann schnell, wenn es viel Speicher gibt, den auf 200MB zu begrenzen dürfte grad bei heutzutage Verfügbarem Speicher kontraproduktiv sein...
 
Ich nutze Launch4j als Wrapper für die Konvertierung der jar in die exe Datei.
Ich hatte das Problem, dass ich bei der Ausführung der jar Datei einen HeapSize Error bekomme wegen zu geringem Speicher. Dies habe ich dadurch gelöst, dass ich im Wrapper
die JVM Option:
-Xmx1024M

gesetzt habe.
Nun habe ich die JVM Options:
-XX:+UseConcMarkSweepGC
-XX:+UseParNewGC
-XX:+CMSParallelRemarkEnabled

zusätzlich ausprobiert, mit dem Ergebniss, dass nun der Speicher sich langsamer füllt und
der CPU allerdings stärker ausgelastet ist.
Eine Extreme Verbesserung fand dadurch bisher vermutlich nicht statt.

In der Umgebung NetBeans habe ich dieses Problem nicht, weil NetBeans die Regulierung im Hintergrund
vornimmt, d.h. VISUALVM zeigt mir dort an, dass HeapSize maximal bei 250-300MB liegt
und der Used Heap bei ca. 150-200MB mit stabil laufendem Programm.
Deswegen muss es ja "irgendwie" funktionieren.

System.gc() habe ich benutzt, weil das Internet von dieser Empfehlung voll ist, d.h. "Java übernimmt
die Säuberung von selbst im Vergleich zu C++"..
 
Hast du die noch nicht konvertierte Jar mal mit VISUALVM ohne Netbeans laufen lassen?


System.gc() habe ich benutzt, weil das Internet von dieser Empfehlung voll ist, d.h. "Java übernimmt
die Säuberung von selbst im Vergleich zu C++"..
Im Internet steht vieles...
Java macht das ja auch selber, deshalb soll man es nicht extra aufrufen.
 
Das kann ich so ehrlich gesagt nicht beurteilen (Wie findet man dies denn heraus?).
Ich habe im Wrapper nur die Möglichkeit, eine Min und Max JRE version auszuwählen.
Min JRE version: "Prefer public JRE, but use JDK runtime if newer"
Max JRE version: "First 64-bit, then 32-bit"

Danke für die Links, leider scheint dies alles wieder nicht auf die schnelle Lösbar zu sein; wirklich
etwas ärgerlich dass man bei Java mit allen möglichen Problemen konfrontiert wird, wenn man
ein Programm außerhalb der Entw. umgebung ausführen möchte..
 
Wie oben geschrieben bekomme ich dann einen Heap Size Error, weil die JVM nicht wie in NetBeans 1024M zu Verfügung stellt, deswegen bisher der Wrapper
 
Hast du mal versucht Xmx höher zu setzten?

java.lang.OutOfMemoryError heißt, der Platz wird wirklich gebraucht, und auch der GC kann da nichts dran ändern, nur deine Programmlogik.
Die Frage ist, warum verbraucht es in der IDE nicht so viel Speicher...

Danke für die Links, leider scheint dies alles wieder nicht auf die schnelle Lösbar zu sein; wirklich
etwas ärgerlich dass man bei Java mit allen möglichen Problemen konfrontiert wird, wenn man
ein Programm außerhalb der Entw. umgebung ausführen möchte..
Zu viel Speicherverbrauch ist halt kein Problem, was man von außen lösen kann 😉
Die IDE hat da nichts mit zu tun, abgesehen von Race-Conditions durch Pfade etc (und JVM-Einstellungen, bei denen man aber selten vom Standard abweichen muss)
 
1024MB war bisher das Limit in NetBeans, mit dem Wrapper habe ich noch keine höheren Werte getestest.
Allerdings suche ich auch nach einer nachhaltigen Lösung und da NetBeans es schafft den Verbrauch
konstant zu halten wird es eine Lösung geben.

Ich werde es nochmal mit jmx und einem Konsolenbefehl versuchen..
 
Google: netbeans default heapsize
Ergebnis:
NetBeans 6.x+ note

Since version 6.0, NetBeans defaults to dynamically setting its Xmx heap size limit to something like 1/3 or 1/4 of the RAM installed on the system. For that reason there's no -J-Xmx value set in the default netbeans.conf. If you find that the automatically selected limit is too little/too much, you can of course still add an appropriate -J-Xmx... option to your netbeans.conf) to override the automatically selected limit.
Das wird also höchstwahrscheinlich mehr sein als das was du deinem Programm manuell gibst.

p.s.
Warum willst du überhaupt die HeapSize extra gering halten?
 
Ich will ab und zu das Programm mehrmals starten um z.B. 2 Optimierungen gleichzeitig laufen zu lassen, deswegen will ich möglichst hohe Effizienz erreichen.
Ich werde Das Anheben mal versuchen, habe mich aber geiirt, der Speicherverlauf ist in NetBeans vermutlich doch derselbe...
Außerdem werde ich jetzt versuchen, meinen Code zu verbessern, da ich vorher fälschlicherweise glaubte, dass System.gc() vorhandenen Speicher für mich leert..
 
Und der Speicher den du ihm gibts gilt natürlich auch nur pro JVM. Wenn du deine Anwendung mehrfach startest gilt für jede diese Grenze natürlich wieder neu. Und das was deine Anwendung halt nun mal braucht wird sie sich nehmen. Oder du kriegst deine OutOfMemoryException.
 
Habe festgestellt, dass bei mir eine 32 bit Version lief, habe die 64bit Version installiert und die HeapSize
nun auf 4GB angehoben. Hoffe es bringt ausreichend etwas..
 
Sicher ??
Wir hatten hier in der Firma schon Probleme mit dem Programmstart unserer Anwendung auf Rechnern, auf denen nur die 64-bit-Version lief !!
 
Java selbst nutzt natürlich auch native Libraries, um überhaupt funktionieren zu können.
So lange man keine 64 Bit Daten braucht, sollte man das Datenmodell auf 32 Bit lassen, damit die Ausführung in 32 und 64 Bit garantiert identisch ist (so weit man das beeinflussen kann).
 
Java selbst nutzt natürlich auch native Libraries, um überhaupt funktionieren zu können.
So lange man keine 64 Bit Daten braucht, sollte man das Datenmodell auf 32 Bit lassen, damit die Ausführung in 32 und 64 Bit garantiert identisch ist (so weit man das beeinflussen kann).

Man kann das "Datenmodel" in Java nicht beeinflussen. Wenn man nicht selbst native libs einbindet, gibt es keinen Unterschied bei der Ausführung in 32 oder 64 bit. Die nativen Standard-Libs sind mit dem JRE installiert, und machen keinen Unterscheid bei der Ausführung.
 
Zuletzt bearbeitet:
Ok, ich hab bisher geglaubt, dafür wäre der -d32/-d64 Umschalter da.
Code:
...
wobei options Folgendes umfasst:
    -d32          Verwendet ein 32-Bit-Datenmodell, sofern verfügbar
    -d64          Verwendet ein 64-Bit-Datenmodell, sofern verfügbar
Habe es jetzt getestet, -d32 funktioniert mit der 64 Bit Java Umgebung gar nicht, mit -d64 oder ohne Einstellung hat ein Integer auch mit 64-Bit-Java lediglich 32 Bit.

Dann hat sich das wohl erledigt.
 
Nuja, ich stamme noch aus der Zeit, als der Integer nur 16 Bit hatte und vertraute auf die Definition, dass ein Integer immer einen kompletten Block im Speicher belegt (je nach Datenmodell 16,32,64 Bit). Gebraucht hab ich mehr als 32 Bit noch nicht, habe mich deshalb noch nie damit beschäftigt.
Wozu die -d32 und -d64 Schalter gut sind, verstehe ich jetzt wirklich nciht mehr. Die 32 BIt JRE lässt -d64 nicht zu und umgekehrt.
 
Von den Java Docs:
The options -d32 and -d64 have been added to the Java launcher to specify whether the program is to be run in a 32 or 64-bit environment. On Solaris these correspond to the ILP32 and LP64 data models, respectively. Since Solaris has both a 32 and 64-bit J2SE implementation contained within the same installation of Java, you can specify either version. If neither -d32 nor -d64 is specified, the default is to run in a 32-bit environment.
Other Java commands (javac, javadoc, etc.) will rarely need to be executed in a 64-bit environment. However, the -d32/-d64 options may be passed to these commands and then on to the Java launcher using the established -J prefix option (eg: -J-d64).
All other platforms (Windows and Linux) contain separate 32 and 64-bit installation packages. If both packages are installed on a system, you select one or the other by adding the appropriate "bin" directory to your path. For consistency, the Java implementations on Linux accept the -d64 option.

kurz: die d32/d64 switches sind nur für gebündelte JREs gut, wie z.b. auf Solaris, dort wird die 32 und 64 Bit version in einer Installation geliefert. Auf anderen Platformen hingegen werden separate Installationen ausgeliefert und daher bringt der switch dort nichts
 

Zurück
Oben