Garbage Collector funktioniert nicht richtig?

Status
Nicht offen für weitere Antworten.

pocketom

Bekanntes Mitglied
Hi,

ich weis das wurde schon oft in der ein oder anderen Form angesprochen. Ich finde aber leider keinen vernünftigen Post der mir dieses Phänomen so erklärt das ich es lösen könnte, das simple Beispiel das ich weiter unten konstruiert habe widerspricht sich mit all dem was ich über den GC gelesen habe.
Deshalb habe ich das kleine Programm geschrieben, mit dem kann man gut demonstrieren wie sich der Hauptspeicher rapide vollmüllt. Ich finde einfach keine Möglichkeit den Speicher aufzuäumen, und das obwohl das Programm nur sehr wenige Zeilen Code hat und doch eigentlich super überschaubar ist!! ! :autsch:


Das "Programm" hat eigentlich kaum Code, es hat zwei Buttons, mit dem einen erzeugt man "Müll", sprich ein 10M großes Array, mit dem anderen Button ruft man einfach nur den Garbage Collector auf. Der System.gc() tut aber einfach mal garnichts!!! Was ist das für ein Mist???
Referenzen dürfen eigentlich nicht mehr vorhanden sein da der Müll doch eh in einem eigenen Block erzeugt wird, der explizite Aufruf des GC sollte also eh überflüssig sein...?
Ich raffs einfach nicht, es ist zum heulen :bahnhof:

Code:
import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.MenuItem;
import org.eclipse.swt.widgets.Shell;


public class AppMain{    
	
	
	public static void main(String[] args) throws Exception
	{	
		Display display = new Display();
		final Shell shell = new Shell(display);
		shell.setLayout(grd);
		shell.open();
		
		// Dropdownmenu
		Menu bar = new Menu (shell, SWT.BAR);
		shell.setMenuBar (bar);
		MenuItem fileItem = new MenuItem (bar, SWT.CASCADE);
		fileItem.setText ("&File");
			// Submenu			
			Menu filesubmenu = new Menu (shell, SWT.DROP_DOWN);
			fileItem.setMenu (filesubmenu);
			
			
				
				// Menuitem Use Memory
				MenuItem usemem_item = new MenuItem (filesubmenu, SWT.PUSH);
				usemem_item.setText ("Use Memory");

				usemem_item.addListener (SWT.Selection, new Listener () {
					public void handleEvent (Event e) {
						
						////////////////////////////
						// MAKE A LOT OF GARBAGE //
						//////////////////////////
						int arraysize = 10000000;
						char chararray[] = new char[arraysize];
						
						for(int i=0;i<arraysize ;i++)
							chararray[i]=0;						
					}
				});				
				
				// Menuitem Run GC
				MenuItem gc_item = new MenuItem (filesubmenu, SWT.PUSH);
				gc_item.setText ("Run GC");

				gc_item.addListener (SWT.Selection, new Listener () {
					public void handleEvent (Event e) 
					{						
						/////////////////////////
						// COLLECT GARBAGE !!!//
						///////////////////////
						System.gc();
					}
				});

		while (!shell.isDisposed ()) {
			if (!display.readAndDispatch ()) display.sleep ();
		}		
		display.dispose ();
	}
}
 
B

Beni

Gast
"gc()" bittet die VM nur den Garbage Collector laufen zu lassen, aber es gibt keine Garantien, dass er tatsächlich aufgerufen wird.

Der GC sollte auf jedenfall automatisch anspringen, wenn der Speicher knapp wird.
 

Wildcard

Top Contributor
Davon abgesehen kann ein Objekt nicht mit einem Durchlauf zerstört werden, dafür sind mindestens 2 nötig.
Erst muss der finalizer aufgerufen werden und danach geprüft werden ob ein Zombie entstanden ist.
 

pocketom

Bekanntes Mitglied
D.h. was müsste ich effektiv in meinem Beispiel tun um Speicher freiwerden zu lassen (aussser die Anwendung beenden, das ist das einzige mir bekannte was funktioniert)? Den GC zwei mal laufen lassen bringt auch nix. Ich möchte auf keinen Fall warten bis der Speicher komplett vollgelaufen ist und dann hoffen das der GC sich gnädig zeigt. Auf meinem Rechner laufen schliesslich noch andere Sachen, da es ein Server ist können da auch jederzeit Sachen gestartet werden, darauf muss man doch auch in Java Rücksicht nehmen können oder? :?
 

Wildcard

Top Contributor
Du musst erstmal unterscheiden zwischen Speicher den die VM verwendet und Speicher der allokiert wurde.
Einmal allokierter Speicher wird nicht sofort freigegeben, falls er wieder gebraucht wird (denn der Vorgang ist teuer).
Das heißt, dein Java Prozess hat einen gewissen Speicherbereich, verwaltet diesen allerdings selbst und hat in diesem Bereich noch Platz sobald das Array freigegeben ist.
Wenn du ein aggressiveres Verhalten möchtest, lässt sich das teilweise über VM Parameter regulieren.
Solche Mini-Beispiele sollte man aber auch nicht überbewerten, da sie mit einem realen Programm wenig gemein haben :wink:
 

Jango

Gesperrter Benutzer
Der GC hat als Thread eine sehr niedrige Priorität und springt möglicherweise garnicht an (ausgenommen der Heap ist voll). Gönne deinem Programm mal ne Ruhephase, damit der GC auch seine Arbeit machen kann.
 

pocketom

Bekanntes Mitglied
Das Problem ist, in meinem realen Beispiel öffne ich recht große Dateien(>100 MB, in naher Zukunft bis zu 500 MB), was wir ja in einem anderen Thread bereits ausführlich besprochen haben (www.java-forum.org/de/topic50831_gc-warning-repeated-allocation-of-very-large-block.html). Das Öffnen, Parsen und Speichern geht mittlerweile sehr flott, nicht zuletzt dank der Hilfe von Wildcard und ein paar anderen Usern aus diesem Forum. Darüber bin ich auch sehr zufrieden. Entschliesst sich der User jedoch 3-4 solcher Dateien zu öffnen ohne das Programm zwischendurch zu schliessen, dann hat man ruckzuck 2 GB im RAM, danach gehts eiskalt ans auslagern. Der GC tut absolut nichts. Das kann so einfach nicht richtig sein.

Ich vermute das es mit den Listenern zusammenhängt. Das Listener Konzept ist meiner Meinung nach eine sehr fragwürde Sache. Über den Menüpunkt rufe ich meine Funktion FileOpen() auf, sprich im Listener des Buttons. Dort wird ein Object namens FileParser erzeugt, die Methode FileParser.read(File file) liefert dann die Objektrepräsentation des Files zurück(Megaobjekt, da Collection mit 200 000 - 1 000 000 Objekten), geht aber wiegesagt prima und sauflott. Da ich danach rechenintensive Methoden immer stets über die gesamte Collection laufen lasse und unter anderem sortiere ist das auch notwendig und sinnvoll. Ich habe ein einziges Objekt von diesem Datentyp, das wird zu Beginn (leer) unter main() erzeugt und stets mit dem Rückgabwert von read(file) überschrieben.

Der Listener sollte meiner Meinung nach trotzdem keine Referenz mehr auf das erzeugte Objekt halten können( Objekt wird schliesslich in einer eigenen Funktion erzeugt, also in einem eigenen Block, das alte wird überschrieben).
Wenn man jedoch erneut ein File öffnet MUSS das alte Object verworfen werden! Ich meine, natürlich habe ich auch schon längst über eine FileClose() Funktion nachgedacht, in C++ würde ich mein Object einfach zerstören und dabei drauf achten das kein Thread mehr drauf zugreift. Kann ich hier aber scheinbar garnicht machen, eine FileCLose() Funktion macht also überhaupt keinen Sinn. Es muss doch eine Lösung geben. Ich kann nicht drauf warten das Gott dem GC irgendwann in den Allerwertesten tritt :cry:
 

byte

Top Contributor
Läuft denn da am Ende der Heap voll? Ist schon komisch. Der GC sollte auf jeden Fall anspringen, bevor der Speicher volläuft.

Hast Du das selbe Beispiel mal mit Swing getestet? Meine Vermutung ist, dass es ein SWT-Problem sein könnte. Bei SWT musst Du ja z.B. selbst erzeugte Widgets auch selbst disposen, bevor der GC sie entfernen kann. Evtl. trifft ja ähnliches auf die Listener zu (was natürlich dämlich wäre).
 

tfa

Top Contributor
pocketom hat gesagt.:
Das Problem ist, in meinem realen Beispiel öffne ich recht große Dateien(>100 MB, in naher Zukunft bis zu 500 MB), was wir ja in einem anderen Thread bereits ausführlich besprochen haben (www.java-forum.org/de/topic50831_gc-warning-repeated-allocation-of-very-large-block.html). Das Öffnen, Parsen und Speichern geht mittlerweile sehr flott, nicht zuletzt dank der Hilfe von Wildcard und ein paar anderen Usern aus diesem Forum. Darüber bin ich auch sehr zufrieden. Entschliesst sich der User jedoch 3-4 solcher Dateien zu öffnen ohne das Programm zwischendurch zu schliessen, dann hat man ruckzuck 2 GB im RAM, danach gehts eiskalt ans auslagern. Der GC tut absolut nichts. Das kann so einfach nicht richtig sein.

Wie kontrollierst Du denn, ob der GC was tut? Nur mit dem Taskmanager?
Lass Dir mal das anzeigen, was Runtime.freeMemory(), Runtime.maxMemory() und Runtime.totalMemory() zurückliefern. Der Taskmanager bekommt von den GC-Aktivitäten zunächst nichts mit, da der vom BS allozierte Speicher nicht sofort zurückgegeben wird, wie Wildcard schon schrieb.

Thomas
 

pocketom

Bekanntes Mitglied
Hi,

also, ich habe jetzt mal vor dem Laden in die FileOpen() Funktion folgendes eingebaut:


Runtime.getRuntime().runFinalization();
System.gc();
Runtime.getRuntime().gc();


mir ist recht bald aufgefallen das ich jetzt mehr Dateien hintereinander laden muss um den entsprechenden Workload zu erzeugen. Das habe ich dann auch nochmal Runtime.freeMemory() und Runtime.totalMemory() überprüft(Runtime.maxMemory() liefert den die Größe des maximalen Adressbereichs, liegt anscheinend irgendwo bei 16 TB):


free: 520192
tota: 2125824
free: 2514944
tota: 230895616
free: 38739968
tota: 491991040
free: 43057152
tota: 718483456
free: 134664192
tota: 961753088
free: 116969472
tota: 970141696
free: 115843072
tota: 978530304



Siehe da, jetzt ist irgendwann Schluss, und zwar in etwa wenn in meinem RAM 1,4 GB liegen. Das ist schonmal um Klassen besser so. Leider immernoch knapp 1 GB das übeflüssig da rumliegt. Würd ich ja auch noch gern loswerden.

Bin bei meiner Recherche auf "Weak References" und andere Arten von References gestossen. Steige da nur leider überhaupt nicht durch, bzw. ob das hilfreich sein könnte oder ob eher irgendwas gegen den Einsatz spricht kann ich im Moment nicht so wirklich beurteilen. Was meint Ihr dazu?

Edit: Ich werde sobald als möglich auf SWING umsteigen. Davon hab ich zwar null Ahnung, hoffe aber das ich wenigstens teilwese das Wissen das ich durch SWT gewonnen habe gebrauchen kann.
 

Wildcard

Top Contributor
Die WeakReferenzes werden deine Bedenken bezüglich den Listenern zerstören :wink:
An sich ist ein explizites abhängen der Listener zu bevorzugen (deshalb muss es immer eine removeListener Methode geben), aber es gibt Spezialfälle in denen das nicht möglich ist.
Hier eignen sich WeakReferences sehr gut um WeakListener zu bauen.
 

pocketom

Bekanntes Mitglied
Hmm, da ich die Funktion ja aus meinem Dropdownmenu auswähle (ganz normales Standardmenü: File -> Open, File -> Save,....)kann ich den Listener ja im Prinzip nicht aushängen oder etwa doch?

Bzgl. der weak references habe ich mal einen neuen thread gestartet da das offenbar noch nicht so recht diskutiert wurde hier. So haben es andere User evtl. auch leichter einen Ansatz zur Verwendung dieser weak references zu erhalten:

Speicherresourcen schonen - WeakReferences richtig einsetzen
 
Status
Nicht offen für weitere Antworten.
Ähnliche Java Themen
  Titel Forum Antworten Datum
J Garbage collector Allgemeine Java-Themen 3
D Garbage Collector Allgemeine Java-Themen 3
A Garbage Collector Allgemeine Java-Themen 3
A Garbage Collector in NetBeans vs. exe Anwendung Allgemeine Java-Themen 33
L Garbage Collector lässt Programm kurz hängen Allgemeine Java-Themen 10
H2SO3- SCJP garbage collector frage Allgemeine Java-Themen 13
R Garbage Collector löscht anscheinend nichts Allgemeine Java-Themen 22
S Garbage Collector entlasten Allgemeine Java-Themen 2
JStickman Der Garbage Collector Allgemeine Java-Themen 13
P Threads ohne Referenz & der Garbage Collector Allgemeine Java-Themen 2
S garbage collector prog Allgemeine Java-Themen 4
S Threads <-> Garbage Collector Allgemeine Java-Themen 2
M Java Garbage Collector Frage (Singleton Pattern) Allgemeine Java-Themen 13
M Problem mit garbage collector Allgemeine Java-Themen 19
R Garbage Collector rennt die ganze Zeit Allgemeine Java-Themen 7
M Garbage Collector Allgemeine Java-Themen 5
T Garbage Collection Frage Allgemeine Java-Themen 15
B Garbage Collection Logfile: Binary File Allgemeine Java-Themen 2
hdi Garbage Collection Allgemeine Java-Themen 12
T Objekt der Garbage Collection zugaenglich machen? Allgemeine Java-Themen 7
F Frage zu Memory Leak, Garbage Collection und Profiler-Tools Allgemeine Java-Themen 6
M Wie lange dauert ein garbage collection Allgemeine Java-Themen 7
R Garbage Collection bei gegenseitiger Objektreferenz Allgemeine Java-Themen 2
M Garbage manuell loswerden Allgemeine Java-Themen 29
M garbage collection Allgemeine Java-Themen 14
G Frage zur Garbage Collection Allgemeine Java-Themen 5
H Collector Generics Problem (incl. Stream & Lambda) Allgemeine Java-Themen 4
P Grabage Collector Allgemeine Java-Themen 8
V Wie funktioniert das Schlüsselwort "final" von Java? Allgemeine Java-Themen 19
M Apache Proxy Weiterleitung auf Tomcat funktioniert nicht wie gewünscht Allgemeine Java-Themen 1
W While Schleife funktioniert nicht ganz Allgemeine Java-Themen 4
H do-while Schleife funktioniert nicht wie ich es möchte Allgemeine Java-Themen 7
ERlK JDA Code funktioniert nicht? Allgemeine Java-Themen 4
B HeapSort für Array of Strings funktioniert nur teilweise Allgemeine Java-Themen 3
stormyark TikTakToe funktioniert nicht Allgemeine Java-Themen 10
T Remove bei ArrayList funktioniert nicht Allgemeine Java-Themen 2
M Map<String,String>funktioniert nicht richtig Allgemeine Java-Themen 4
P String.replace() funktioniert nicht? Allgemeine Java-Themen 3
boschl2000 Springerproblem-Implementierung funktioniert nicht richtig Allgemeine Java-Themen 1
F Getter Methode aufrufen funktioniert nicht Allgemeine Java-Themen 1
N Regulärer Ausdruck funktioniert nicht Allgemeine Java-Themen 6
Lukas2904 Wie funktioniert ein KeyLogger? Allgemeine Java-Themen 3
Tobero Meine Funktion für das beinhalten eines Punktes in einem Kreis funktioniert nicht Allgemeine Java-Themen 5
1Raini Java if-Abfrage funktioniert nicht! Allgemeine Java-Themen 3
Killunox MaxHeap Zuweisung unter Linux funktioniert nicht Allgemeine Java-Themen 1
I Wieso funktioniert das nich? Allgemeine Java-Themen 5
Dann07 MP3 Datei abspielen funktioniert nicht Allgemeine Java-Themen 6
O Aus JAR-Datei erstellte EXE-Datei funktioniert nicht Allgemeine Java-Themen 10
A Mp3 Player funktioniert nicht Allgemeine Java-Themen 0
X JNA funktioniert nicht mehr Allgemeine Java-Themen 4
bueseb84 FolderWatcher mit WatchService funktioniert nur bedingt Allgemeine Java-Themen 5
Drachenbauer Division mit Int funktioniert nicht Allgemeine Java-Themen 3
O docx-Datei erzeugung mit DocXStamper funktioniert nicht Allgemeine Java-Themen 2
F Schleife funktioniert nicht richtig Allgemeine Java-Themen 13
T Split() Methode funktioniert nicht?! Allgemeine Java-Themen 11
L Tesseract-OCR 4.0 unter Linux funktioniert nicht Allgemeine Java-Themen 3
J Wie konkret funktioniert das Modulsystem unter Java 11? Allgemeine Java-Themen 4
J Neuronales Netz funktioniert mal und mal nicht. Allgemeine Java-Themen 3
T Umlaute in Eclipse einlesen funktioniert nicht Allgemeine Java-Themen 16
A Methodenaufruf funktioniert nicht richtig Allgemeine Java-Themen 5
C WindowBuilder Design funktioniert nicht Allgemeine Java-Themen 0
J FTPSClient funktioniert nicht Allgemeine Java-Themen 4
H IDEA IntelliJ Java Mail funktioniert nach Export nicht mehr! Allgemeine Java-Themen 1
M Operatoren Warum funktioniert diese überprüfung nicht? Allgemeine Java-Themen 7
R jar-Datei funktioniert nicht Allgemeine Java-Themen 2
E Open Declaration Funktioniert nicht Allgemeine Java-Themen 0
R Verschlüsselung funktioniert nicht Allgemeine Java-Themen 5
RalleYTN requires transitive funktioniert nicht? Allgemeine Java-Themen 7
R Bruteforce hashes mit multithreading. Funktioniert das so? Allgemeine Java-Themen 0
P Best Practice Wieso funktioniert der Modulo - Operator nicht? Allgemeine Java-Themen 2
HarleyDavidson Eigener PropertyChangeListener funktioniert einfach nicht Allgemeine Java-Themen 3
J Exclude funktioniert nicht Allgemeine Java-Themen 2
K .jar funktioniert nicht vollständig Allgemeine Java-Themen 1
P Java https proxy (-Dhttps.proxyHost) Start-Parameter funktioniert nicht? Allgemeine Java-Themen 2
L Auswertung eines Testes funktioniert nicht Allgemeine Java-Themen 37
O Fahrenheit/Celsius Converter funktioniert nicht Allgemeine Java-Themen 2
M Serialisierung funktioniert nicht Allgemeine Java-Themen 9
D Collections.sort funktioniert nicht in exportierten .class Dateien Allgemeine Java-Themen 10
J Arrays auf gleichheit untersuchen funktioniert nicht Allgemeine Java-Themen 11
P GUI: ArrayList anzeigen funktioniert nicht Allgemeine Java-Themen 5
H Timer funktioniert nicht? Allgemeine Java-Themen 3
R javax.comm --> Programm funktioniert nach Export nicht mehr Allgemeine Java-Themen 0
O Mein JButton Array funktioniert nicht Allgemeine Java-Themen 3
R Erste Schritte Object reference funktioniert nicht. Wie mach ichs richtig? Allgemeine Java-Themen 3
J If Abfrage funktioniert nicht Allgemeine Java-Themen 4
R Objekt funktioniert nicht auf iOS Allgemeine Java-Themen 15
U PersistenceManager.createEntityManager funktioniert nicht Allgemeine Java-Themen 3
D Java Datei nach Eclipse Export funktioniert nicht Allgemeine Java-Themen 0
M Eigene forEach()-Methode funktioniert nicht. Allgemeine Java-Themen 2
H File.listFiles() funktioniert nicht... Allgemeine Java-Themen 10
JG12111989 Auswertung von Fragebogen funktioniert nicht! Allgemeine Java-Themen 7
M Primzahlberechnung funktioniert nicht. Allgemeine Java-Themen 4
A JFreeChart funktioniert nicht :( Allgemeine Java-Themen 6
C file.delete() funktioniert bei zweiten aufruf nicht mehr Allgemeine Java-Themen 3
F Datei einlesen funktioniert nicht Allgemeine Java-Themen 3
A Debugger im Java-Editor funktioniert nicht Allgemeine Java-Themen 5
B DB-Zugriff einer Webanwendung funktioniert nicht mit Java 7 Allgemeine Java-Themen 2
B Web-Anwendung funktioniert mit Java 1.8, aber nicht mit Java 1.7 (auf Client) Allgemeine Java-Themen 5
J Swing Cursor.WAIT funktioniert nicht nach JFileChooser Allgemeine Java-Themen 1
P Wie funktioniert das Feedback eines Klicks auf eine Java GUI Allgemeine Java-Themen 10

Ähnliche Java Themen

Neue Themen


Oben