Memory Leaks
12 posts
• Page 1 of 1
Memory Leaks
Ich habe die Beispiel-Applikation einmal ausprobiert und den Client-Part mit JVisualVM unter die Lupe genommen.
Dabei ist mir aufgefallen, dass der JVx-Client sehr ineffizient mit Speicher umgeht und damit möglicherweise Schuld an einigen Ausfällen meiner Software ist.
Ich verwende durchaus komplexe Fenster mit einer Vielzahl an Komponenten. Wie es aussieht werden aber Resourcen (nach meiner Analyse bis hin zur View-Technologie z.B. Swing) nur selten auch wieder freigegeben.
In der Beispiel-Applikation belegt schon das einfache Fenster apps.firstapp.frames.DBEditFrame nach 40 maligem Öffnen und Schließen ca. 10 KB Heap-Space.
Sicherlich ist ein 40 maliges Öffnen und Schließen der Fenster kein erwartetes Nutzungsverhalten, allerdings treten in meiner Anwendung sehr oft OutOfMemoryExceptions auf. Dabei sind die resistentensten Objekte auf dem Heap, die durch eine Garbage Collection nicht mehr entfernt werden können, jene aus der JVx Client Library.
Speicheranalyse:
Dabei ist mir aufgefallen, dass der JVx-Client sehr ineffizient mit Speicher umgeht und damit möglicherweise Schuld an einigen Ausfällen meiner Software ist.
Ich verwende durchaus komplexe Fenster mit einer Vielzahl an Komponenten. Wie es aussieht werden aber Resourcen (nach meiner Analyse bis hin zur View-Technologie z.B. Swing) nur selten auch wieder freigegeben.
In der Beispiel-Applikation belegt schon das einfache Fenster apps.firstapp.frames.DBEditFrame nach 40 maligem Öffnen und Schließen ca. 10 KB Heap-Space.
Sicherlich ist ein 40 maliges Öffnen und Schließen der Fenster kein erwartetes Nutzungsverhalten, allerdings treten in meiner Anwendung sehr oft OutOfMemoryExceptions auf. Dabei sind die resistentensten Objekte auf dem Heap, die durch eine Garbage Collection nicht mehr entfernt werden können, jene aus der JVx Client Library.
Speicheranalyse:
- javac
- Posts: 7
- Joined: Wed Jun 17, 2015 11:22 am
Re: Memory Leaks
Das Problem mit den Ressourcen ist ein mehr oder weniger Swing Problem. Das Problem wurde bereits im aktuellen Entwicklungsstand behoben.
Der JInternalFrame wird nicht wieder freigegeben und daher bleiben auch eine Menge Ressourcen im Speicher. (Ist aber z.B. nich mit JVM 5, aber das ist hier irrelevant)
Es kann natürlich sein das unsere Problembehebung nicht für ihr Problem zutrifft. Aber es wäre gut, wenn Sie ev. einen nightly build ausprobieren würden und uns dann das Feedback zu posten.
Nach unserer Problembehebung sollte max. 1 Fenster zurückbleiben, da der KeyboardFocusManager eine Referenz darauf hält. Beim Öffnen eines neuen Fensters sollte dann diese Ressource auch durch den GC freigegeben werden (nach unbestimmter Zeit oder wenn eben nötig).
Der JInternalFrame wird nicht wieder freigegeben und daher bleiben auch eine Menge Ressourcen im Speicher. (Ist aber z.B. nich mit JVM 5, aber das ist hier irrelevant)
Es kann natürlich sein das unsere Problembehebung nicht für ihr Problem zutrifft. Aber es wäre gut, wenn Sie ev. einen nightly build ausprobieren würden und uns dann das Feedback zu posten.
Nach unserer Problembehebung sollte max. 1 Fenster zurückbleiben, da der KeyboardFocusManager eine Referenz darauf hält. Beim Öffnen eines neuen Fensters sollte dann diese Ressource auch durch den GC freigegeben werden (nach unbestimmter Zeit oder wenn eben nötig).
-
Development@SIB - Posts: 325
- Joined: Mon Sep 28, 2009 1:54 pm
Re: Memory Leaks
Das Thema Ressourcen freigeben können wir nicht bestätigen. Von JVx werden die DataBooks/Connections/LCOs solange gehalten wie sie auch benötigt werden. Aber wenn Sie genauere Analysen haben, sind diese nicht uninteressant und wenn es bisher unbekannte Probleme geben sollte, dann können diese auch behoben werden.
...Sie müssen Ihre (Sub)Connections Ihrer Fenster zB selbst closen. Das LCO ist ja immer mit einer Connection verbunden und solange die Connection offen bleibt, ist auch das LCO mit all seinen Objekten noch im Speicher.
...Sie müssen Ihre (Sub)Connections Ihrer Fenster zB selbst closen. Das LCO ist ja immer mit einer Connection verbunden und solange die Connection offen bleibt, ist auch das LCO mit all seinen Objekten noch im Speicher.
-
Development@SIB - Posts: 325
- Joined: Mon Sep 28, 2009 1:54 pm
Re: Memory Leaks
Meine Analyse bezog sich nur auf die Client-Applikation. Serverseitig werden alle Referenzen sauber aufgeräumt. Mit dem Nightly-Build der Version 2.4 werden clientseitig endlich auch die Frames freigegeben. Bisher habe ich das mit der Beispiel-Applikation getestet und konnte diese Veränderung feststellen.
Ich werde den Nightlybuild auch in der Hauptsoftware testen und dann erneut eine Analyse durchführen.
Vielen Dank für die hilfreiche Antwort!
Ich werde den Nightlybuild auch in der Hauptsoftware testen und dann erneut eine Analyse durchführen.
Vielen Dank für die hilfreiche Antwort!
- javac
- Posts: 7
- Joined: Wed Jun 17, 2015 11:22 am
Re: Memory Leaks
Sehr schön.
Uns würde interessieren wofür Sie JVx einsetzen bzw. haben Sie evtl. Screenshots von Ihrer Software. Das Entwickler Team freut sich immer sehr über Anwendungen die mit JVx erstellt wurden.
Haben Sie evtl. sonstige Anregungen oder Feedback für das Entwickler Team?
Uns würde interessieren wofür Sie JVx einsetzen bzw. haben Sie evtl. Screenshots von Ihrer Software. Das Entwickler Team freut sich immer sehr über Anwendungen die mit JVx erstellt wurden.
Haben Sie evtl. sonstige Anregungen oder Feedback für das Entwickler Team?
-
Support@SIB - Posts: 353
- Joined: Mon Sep 28, 2009 1:56 pm
Re: Memory Leaks
Eine Frage hätte ich noch bezüglich möglicher Memory Leaks:
Die Klasse JVxUtil übersetzt nach meinem Verständnis Datentypen auf Instanzen vom Typ ICellEditor. Diese sorgen im Endeffekt dafür, dass eine Komponente mit einem CellEditorComponent ausgestattet werden kann. Dies sind in meinem Fall Swing Komponenten. Schaut man sich die Klasse com.sibvisions.rad.ui.swing.ext.JVxUtil an erkennt man, dass statische finale Konstanten für drei Instanzen angelegt werden.
Diese Instanzen werden in meiner Anwendung offenbar sehr häufig referenziert, da sie durch die Methode
Bezüglich des Heaps können also folgende Referenzen entstehen:
Seit ich die statische Kopplung (rechte Seite) gelöst habe, kann ich 53.109 Bytes Speicher einsparen, da 63 Komponenten freigegeben werden können.
Vielleicht könnte sich das nochmal jemand anschauen und mir sagen, ob ich bei der Verwendung der ICellEditor-Instanzen einen Fehler mache oder ob die Implementation von JVxUtil tatsächlich ungünstig für die Garbage Collection ist.
Die Klasse JVxUtil übersetzt nach meinem Verständnis Datentypen auf Instanzen vom Typ ICellEditor. Diese sorgen im Endeffekt dafür, dass eine Komponente mit einem CellEditorComponent ausgestattet werden kann. Dies sind in meinem Fall Swing Komponenten. Schaut man sich die Klasse com.sibvisions.rad.ui.swing.ext.JVxUtil an erkennt man, dass statische finale Konstanten für drei Instanzen angelegt werden.
- Code: Select all
/** the default number cell editor. */
private static final ICellEditor NUMBER_CELL_EDITOR = new JVxNumberCellEditor();
/** the default date cell editor. */
private static final ICellEditor DATE_CELL_EDITOR = new JVxDateCellEditor();
/** the default text cell editor. */
private static final ICellEditor TEXT_CELL_EDITOR = new JVxTextCellEditor();
Diese Instanzen werden in meiner Anwendung offenbar sehr häufig referenziert, da sie durch die Methode
- Code: Select all
public static ICellEditor getDefaultCellEditor(Class<?> pClass)
{
if (pClass == null)
{
return TEXT_CELL_EDITOR;
}
[...]
}
Bezüglich des Heaps können also folgende Referenzen entstehen:
- Code: Select all
Komponenten <-> ICellEditor-Instanz <- Statische Konstante (JVxUtil.TEXT_CELL_EDITOR)
- Die Komponenten auf der linken Seite halten eine Referenz auf die ICellEditor-Instanz. Die ICellEditor-Instanz hält ihrerseits aber auch eine Referenz auf die Komponente.
- Auf der rechten Seite erkennt man, dass das GC Root eine statische Konstante ist. Aus meiner Sicht, ist dies ein Memory Leak, denn die Komponenten auf der linken Seite können niemals vom GC freigegeben werden.
Seit ich die statische Kopplung (rechte Seite) gelöst habe, kann ich 53.109 Bytes Speicher einsparen, da 63 Komponenten freigegeben werden können.
Vielleicht könnte sich das nochmal jemand anschauen und mir sagen, ob ich bei der Verwendung der ICellEditor-Instanzen einen Fehler mache oder ob die Implementation von JVxUtil tatsächlich ungünstig für die Garbage Collection ist.
- javac
- Posts: 7
- Joined: Wed Jun 17, 2015 11:22 am
Re: Memory Leaks
Der statische CellEditor selbst hält keine Referenz nach außen. Der Editor wird immer wieder erzeugt. Der Painter hält für kurze Zeit eine Referenz, aber diese verschwindet auch wieder.
Die ~ 51K sollten nicht weiter ins Gewicht fallen. Da verschwendet Swing schon weit mehr.
Hat Ihre Applikation Memory Probleme oder reagiert träge? Ist der Speicherverlauf ein Problem?
Die ~ 51K sollten nicht weiter ins Gewicht fallen. Da verschwendet Swing schon weit mehr.
Hat Ihre Applikation Memory Probleme oder reagiert träge? Ist der Speicherverlauf ein Problem?
-
Development@SIB - Posts: 325
- Joined: Mon Sep 28, 2009 1:54 pm
Re: Memory Leaks
Können Sie genau sagen, wo der Editor neu erzeugt wird?
Was genau meinen Sie mit "statischem CellEditor"?
Meine Applikation hat insofern Speicherprobleme, als dass ich beobachte, dass über die Laufzeit mehr Speicher benötigt wird, der jedoch nicht wieder freigegeben wird. Meine Analyse zeigt mir, dass die meisten Referenzen, die nicht freigegeben werden können, an einem statischen Konstrukt (wie dem JVxUtil) festgehalten werden.
Auf das Beispiel mit dem ICellEditor bezogen:
Ein und dieselbe Instanz der Klasse com.sibvisions.rad.ui.swing.ext.celleditor.JVxTextCellEditor wird vom JVxUtil als DefaultCellEditor geliefert. Im Code unten erkennt man die Membervariable private DefaultTableCellRenderer cellRenderer dieser Klasse. Diese hält die Referenz auf die CellRendererComponent, die später durch andere Komponenten als Renderer referenziert werden. An genau dieser Stelle gibt es doch eine Referenz zurück zur Komponente, sehe ich das richtig?
Verschwendungen von Speicher seitens von Swing kann ich nicht beobachten, denn sobald die statischen Referenzen im JVxUtil beseitigt sind (z.B. durch erneuern der Instanzen von ICellEditor) werden alle Komponenten durch den GC weggeräumt.
Was genau meinen Sie mit "statischem CellEditor"?
Meine Applikation hat insofern Speicherprobleme, als dass ich beobachte, dass über die Laufzeit mehr Speicher benötigt wird, der jedoch nicht wieder freigegeben wird. Meine Analyse zeigt mir, dass die meisten Referenzen, die nicht freigegeben werden können, an einem statischen Konstrukt (wie dem JVxUtil) festgehalten werden.
Auf das Beispiel mit dem ICellEditor bezogen:
Ein und dieselbe Instanz der Klasse com.sibvisions.rad.ui.swing.ext.celleditor.JVxTextCellEditor wird vom JVxUtil als DefaultCellEditor geliefert. Im Code unten erkennt man die Membervariable private DefaultTableCellRenderer cellRenderer dieser Klasse. Diese hält die Referenz auf die CellRendererComponent, die später durch andere Komponenten als Renderer referenziert werden. An genau dieser Stelle gibt es doch eine Referenz zurück zur Komponente, sehe ich das richtig?
- Code: Select all
public class JVxTextCellEditor extends AbstractTextCellEditor
implements ICellRenderer<JComponent>
{
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Class members
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/** the content type. */
private String contentType;
/** The default Renderer anyway!. */
private DefaultTableCellRenderer cellRenderer = null;
/** The default Renderer anyway!. */
private StringBuilder echoChars = new StringBuilder();
[...]
}
Verschwendungen von Speicher seitens von Swing kann ich nicht beobachten, denn sobald die statischen Referenzen im JVxUtil beseitigt sind (z.B. durch erneuern der Instanzen von ICellEditor) werden alle Komponenten durch den GC weggeräumt.
- javac
- Posts: 7
- Joined: Wed Jun 17, 2015 11:22 am
Re: Memory Leaks
Den CellRenderer gibt es einmal pro statischer Instanz.
Eine Referenz auf den CellRenderer ist egal. Wichtig ist, dass der CellRenderer keine Referenz auf eine Component hat.
Unabhängig davon können nicht mehrere Komponenten eine Referenz auf einen CellRenderer haben, weil in AWT/Swing eine Komponente nur einmal geaddet werden kann, dh eine JTable verwendet einen CellRenderer und addet diesen. (Das adden wäre gar nicht notwendig, macht Swing aber, damit sich Background, Foreground, Font usw. vererben).
Somit hat der Renderer über parent eine Referenz auf die Komponente.
Wenn eine 2. JTable denselben Renderer verwendet, wird dieser von der ersten removed, und der 2. geaddet. Das geht gar nicht anders in AWT/ Swing. Ein add zu einer neuen Komponente removed diese automatisch von der alten.
Swing hat immer schon einen statischen Renderer verwendet, und diesen nie nach dem paint removed. Das sollte eben nur temporär eine Referenz halten, bis der Renderer wieder in einer Tabelle verwendet wird.
Das war eines der Performance/Speicher Tunings von Swing.
Wenn man für eine Tabelle für jede Zelle einen Renderer erzeugt, braucht das zu viel Speicher, ausserdem ist add/ remove teuer, und sollte somit so selten wie möglich gemacht werden.
Eine Referenz auf den CellRenderer ist egal. Wichtig ist, dass der CellRenderer keine Referenz auf eine Component hat.
Unabhängig davon können nicht mehrere Komponenten eine Referenz auf einen CellRenderer haben, weil in AWT/Swing eine Komponente nur einmal geaddet werden kann, dh eine JTable verwendet einen CellRenderer und addet diesen. (Das adden wäre gar nicht notwendig, macht Swing aber, damit sich Background, Foreground, Font usw. vererben).
Somit hat der Renderer über parent eine Referenz auf die Komponente.
Wenn eine 2. JTable denselben Renderer verwendet, wird dieser von der ersten removed, und der 2. geaddet. Das geht gar nicht anders in AWT/ Swing. Ein add zu einer neuen Komponente removed diese automatisch von der alten.
Swing hat immer schon einen statischen Renderer verwendet, und diesen nie nach dem paint removed. Das sollte eben nur temporär eine Referenz halten, bis der Renderer wieder in einer Tabelle verwendet wird.
Das war eines der Performance/Speicher Tunings von Swing.
Wenn man für eine Tabelle für jede Zelle einen Renderer erzeugt, braucht das zu viel Speicher, ausserdem ist add/ remove teuer, und sollte somit so selten wie möglich gemacht werden.
-
Development@SIB - Posts: 325
- Joined: Mon Sep 28, 2009 1:54 pm
Re: Memory Leaks
Der Renderer sollte kein Problem darstellen, da im BasicTableUI:
gemacht wird.
Wir hätten keine Referenzen zum Renderer gefunden. Jetzt hängt es davon ab, wie/womit Sie JVx einsetzen, sprich ob globale DataBooks verwendet werden und ein Screen darauf einen Listener hängt und nicht mehr entfernt oder welches LaF sie einsetzen weil ev. dadurch eine Referenz entsteht.
Wenn Sie genauere Informationen haben, wer welche Instanz referenziert, dann wäre dies hilfreich. In unserem Testszenario sind keinerlei Probleme festzustellen. Natürlich hält Swing einiges an SoftReferences im Speicher, was zu einem späten Freigeben führt, aber das liegt nicht in unseren Händen, da Technologieabhängig.
- Code: Select all
rendererPane.removeAll();
gemacht wird.
Wir hätten keine Referenzen zum Renderer gefunden. Jetzt hängt es davon ab, wie/womit Sie JVx einsetzen, sprich ob globale DataBooks verwendet werden und ein Screen darauf einen Listener hängt und nicht mehr entfernt oder welches LaF sie einsetzen weil ev. dadurch eine Referenz entsteht.
Wenn Sie genauere Informationen haben, wer welche Instanz referenziert, dann wäre dies hilfreich. In unserem Testszenario sind keinerlei Probleme festzustellen. Natürlich hält Swing einiges an SoftReferences im Speicher, was zu einem späten Freigeben führt, aber das liegt nicht in unseren Händen, da Technologieabhängig.
-
Development@SIB - Posts: 325
- Joined: Mon Sep 28, 2009 1:54 pm
Re: Memory Leaks
Tatsächlich habe ich eine merkwürdige Ableitung der Klasse JVxFilterTable gefunden, die offenbar für die gehaltenen Referenzen verantwortlich ist. Dies dürfte allerdings nicht durch JVx herrühren, sondern ist wahrscheinlich ein Fehler in der Erweiterung der Klasse.
Ihren bisherigen Antworten entnehme ich, dass die statischen Referenzen im JVxUtil durchaus gewollt sind und bei richtiger Verwendung in den eigenen Ableitungen nicht zu Memory Leaks führen sollten.
Wenn ich das so richtig verstanden habe, habe ich eine wichtige Antwort erhalten - vielen Dank!
Die JVx Memory Leaks bezüglich der Frames sind durch Einspielen des Nightly-Builds behoben und die restlichen Leaks wahrscheinlich durch eine ungünstige Ableitung von JVx Komponenten meinerseits entstanden.
Ihren bisherigen Antworten entnehme ich, dass die statischen Referenzen im JVxUtil durchaus gewollt sind und bei richtiger Verwendung in den eigenen Ableitungen nicht zu Memory Leaks führen sollten.
Wenn ich das so richtig verstanden habe, habe ich eine wichtige Antwort erhalten - vielen Dank!
Die JVx Memory Leaks bezüglich der Frames sind durch Einspielen des Nightly-Builds behoben und die restlichen Leaks wahrscheinlich durch eine ungünstige Ableitung von JVx Komponenten meinerseits entstanden.
- javac
- Posts: 7
- Joined: Wed Jun 17, 2015 11:22 am
Re: Memory Leaks
JVx wird für sehr "große" Applikationen eingesetzt - mit Millionen Datensätzen und mehreren Hundert Masken und Benutzern. Wir haben bisher von keinen gröberen Speicherproblemen gehört. Natürlich kommt es schon mal vor, aber im Normalfall wurden diese bereits mit Nightly Builds behoben.
Vor allem im Bereich der Oracle Forms Migration muss JVx zuverlässig funktionieren. Denn in diesem Bereich ist man langzeitstabilität gewohnt. Und genau das ermöglicht JVx.
Aber gerade solche Hinweise wie Ihre sind sehr hilfreich um schon frühzeitig die Probleme zu erkennen. Wie bereits erwähnt, würden wir uns über nähere Details über Ihren Einsatz von JVx freuen. Gerade für OpenSource Frameworks ist Feedback ein wichtiger Baustein.
Vor allem im Bereich der Oracle Forms Migration muss JVx zuverlässig funktionieren. Denn in diesem Bereich ist man langzeitstabilität gewohnt. Und genau das ermöglicht JVx.
Aber gerade solche Hinweise wie Ihre sind sehr hilfreich um schon frühzeitig die Probleme zu erkennen. Wie bereits erwähnt, würden wir uns über nähere Details über Ihren Einsatz von JVx freuen. Gerade für OpenSource Frameworks ist Feedback ein wichtiger Baustein.
-
Support@SIB - Posts: 353
- Joined: Mon Sep 28, 2009 1:56 pm
12 posts
• Page 1 of 1