# Garbage Collector in NetBeans vs. exe Anwendung



## AlgoFX90 (23. Jun 2016)

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ß


----------



## VfL_Freak (23. Jun 2016)

Moin,

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



AlgoFX90 hat gesagt.:


> 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


----------



## Thallius (23. Jun 2016)

Was heist du startest es als .exe? Was passiert denn wenn du das jar aus der Console startest?


----------



## mrBrown (23. Jun 2016)

AlgoFX90 hat gesagt.:


> 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...


----------



## AlgoFX90 (23. Jun 2016)

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++"..


----------



## mrBrown (23. Jun 2016)

Hast du die noch nicht konvertierte Jar mal mit VISUALVM ohne Netbeans laufen lassen?




AlgoFX90 hat gesagt.:


> 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.


----------



## VfL_Freak (23. Jun 2016)

hier noch mal schnell einige lesenswerte Links zudem Thema:
http://www.fh-wedel.de/~si/seminare/ws07/Ausarbeitung/05.jvm/jvm2.htm
http://www.heise.de/developer/artik...-von-Java-Programmen-mit-visualgc-227258.html
http://www.angelikalanger.com/Articles/EffectiveJava/27.GCTuning/27.GCTuning.html


----------



## Flown (23. Jun 2016)

Welche VM wird denn bei deiner ".exe" Version verwendet? Die Eingebaute oder eine Installierte?


----------



## AlgoFX90 (23. Jun 2016)

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..


----------



## Flown (23. Jun 2016)

Hast du dein Programm mal ohne Wrapper versucht? Tritt das Problem auch auf?


----------



## AlgoFX90 (23. Jun 2016)

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


----------



## VfL_Freak (23. Jun 2016)

AlgoFX90 hat gesagt.:


> weil die JVM nicht wie in NetBeans 1024M zu Verfügung stellt,


das stellst Du doch über den Startparameter -Xmx1024M ein ...

https://rimuhosting.com/knowledgebase/linux/java/-Xmx-settings


----------



## mrBrown (23. Jun 2016)

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...



AlgoFX90 hat gesagt.:


> 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)


----------



## JStein52 (23. Jun 2016)

Ich glaube der TE ist der irrigen Meinung NetBeans würde die GC durchführen.


----------



## AlgoFX90 (23. Jun 2016)

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..


----------



## JStein52 (24. Jun 2016)

AlgoFX90 hat gesagt.:


> und da NetBeans es schafft den Verbrauch
> konstant zu halten


Noch einmal: NetBeans schafft da gar nichts. Das führt nur deine Anwendung aus ... Es benutzt dazu höchstens Startparameter die du im Wrapper nicht benutzt. Aber es ist ja kein Hexenwerk nachzusehen was in NetBeans als Startparameter für die VM eingestellt ist.


----------



## InfectedBytes (24. Jun 2016)

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?


----------



## AlgoFX90 (24. Jun 2016)

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..


----------



## InfectedBytes (24. Jun 2016)

Hohe Effizienz bekommst du aber nicht durch wenig speicher. Es ist eher umgekehrt, durch mehr Speicher kann der GC effektiver arbeiten


----------



## JStein52 (24. Jun 2016)

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.


----------



## AlgoFX90 (24. Jun 2016)

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..


----------



## VfL_Freak (24. Jun 2016)

Ist es denn auch ein 64-bit-Programm, dass Du laufen lassen willst ?
Sonst wird es ohne 32-bit-JVM schwierig ....


----------



## mrBrown (24. Jun 2016)

VfL_Freak hat gesagt.:


> Ist es denn auch ein 64-bit-Programm, dass Du laufen lassen willst ?
> Sonst wird es ohne 32-bit-JVM schwierig ....


Naja, es ist Java...solange er keine nativen libs benutzt gibts da keinen Unterscheid...


----------



## VfL_Freak (24. Jun 2016)

Sicher ??
Wir hatten hier in der Firma schon Probleme mit dem Programmstart unserer Anwendung auf Rechnern, auf denen nur die 64-bit-Version lief !!


----------



## mrBrown (24. Jun 2016)

VfL_Freak hat gesagt.:


> Sicher ??
> Wir hatten hier in der Firma schon Probleme mit dem Programmstart unserer Anwendung auf Rechnern, auf denen nur die 64-bit-Version lief !!


'ne jar ist bytecode, da gibts keinen Unterscheid  zwischen 32 und 64. Einen Unterschied machen nur native libs.


----------



## VfL_Freak (24. Jun 2016)

hmm, ok ... bei uns kann es natürlich auch mit daran gelegen haben, dass unsere Anwendungen u. a. auch den FF nutzen ....


----------



## Neumi5694 (26. Jun 2016)

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).


----------



## mrBrown (26. Jun 2016)

Neumi5694 hat gesagt.:


> 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.


----------



## Neumi5694 (27. Jun 2016)

Ok, ich hab bisher geglaubt, dafür wäre der -d32/-d64 Umschalter da.

```
...
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.


----------



## JStein52 (27. Jun 2016)

Neumi5694 hat gesagt.:


> hat ein Integer auch mit 64-Bit-Java lediglich 32 Bit


Ja klar ist ein Integer immer 32 Bit gross. Wie @mrBrown schon schrieb, der Bytecode ist der gleiche, wäre ja sonst auch schlimm, Portabilität ist eines der grossen Highlights von Java.


----------



## Neumi5694 (27. Jun 2016)

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.


----------



## InfectedBytes (27. Jun 2016)

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


----------



## Neumi5694 (27. Jun 2016)

Danke.


----------



## mrBrown (27. Jun 2016)

Neumi5694 hat gesagt.:


> 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).


Allerdings ist int bei den meisten Compilern/Sprachen 32 bit, auch auf 64bit Prozessoren...


----------

