Curt Nowak wrote: > Hi Gunnar, > > I am sorry if I appear to be unconvincable but I still don't get it. > You suggested disposing toplevel objects manually which I do (see my code > below). Yet there is a noticeable memory leak left. > I created a couple of dump files of the heap using jconsole and had a look at > those using jhat. My findings are that there are many instances of (ordered > by count) > - > com.trolltech.qt.internal.QSignalEmitterInternal$AbstractSignalInternal$Connection > - com.trolltech.qt.QSignalEmitter$Signal1 > - com.trolltech.qt.QSignalEmitter$Signal0 > - com.trolltech.qt.gui.QHBoxLayout > - com.trolltech.qt.gui.QPushButton > - QtLeak > > Most interestingly the "Instance Counts" (jhat) are much less than the number > of instances that I created when pushing the "create button". Still their > number increases when I hit that button a couple of times more. So it seems > that some toplevel QtLeak objects do get disposed while others don't. How can > that be? > > I ran my sample on Java 1.6.0_06 with qtjambi-win32-gpl-4.4.0_01 under > Windows XP. > > Kind regards, Curt
You're counting java references, we have no control over these as GC will collect them. dispose() will delete the C++ part of the object and leave the java part dead for the gc to collect. dispose() will also delete all C++ objects in the child hierarchy, leaving the buttons and connections etc free for collection too. When the GC does so is completely out of our control. The fact that you see fewer instances than what you created indicates that GC collected some but not all yet. If you do replace your create with: <snip> public static int counter = 0; @SuppressWarnings("unused") private void create() { for(int i=0; i<1000; i++){ Leak leak = new Leak(null) { public void disposed() { counter--; } }; leak.dispose(); ++counter; } System.out.println("total number of Leak objects: " + counter); } </snip> You will see that the counter is always 0, hence there is no longer any C++ objects being retained. > > > import com.trolltech.qt.gui.QApplication; > import com.trolltech.qt.gui.QHBoxLayout; > import com.trolltech.qt.gui.QLayout; > import com.trolltech.qt.gui.QPushButton; > import com.trolltech.qt.gui.QWidget; > > public class QtLeak extends QWidget{ > > public static void main(String[] args) { > QApplication.initialize(args); > > QtLeak testQtLeak = new QtLeak(null); > testQtLeak.show(); > > QApplication.exec(); > } > > public QtLeak(QWidget parent){ > super(parent); > > QLayout layout = new QHBoxLayout(this); > QPushButton buttonCreate = new QPushButton("Create", this); > buttonCreate.clicked.connect(this, "create()"); > layout.addWidget(buttonCreate); > > this.setLayout(layout); > } > > > @SuppressWarnings("unused") > private void create() > { > for(int i=0; i<1000; i++){ > QtLeak leak = new QtLeak(null); > leak.dispose(); > } > } > } > > > ________________________________ > > Von: Gunnar Sletta [mailto:[EMAIL PROTECTED] > Gesendet: Fr 28.11.2008 10:41 > An: Curt Nowak > Cc: qt-jambi-interest@trolltech.com > Betreff: Re: AW: [Qt-jambi-interest] Memory Leaks - any updates? > > > > <snip> > > The problem is still the same though, just with a few levels of > indirection. > > When you do > > button.clicked.connect(this, "create()"); > > you create a reference from the signal to back to the toplevel and you > have a circular reference that is inpenetrable for the garbage collector. > > This is in fact a huge problem, and hopefully we can minimize some of > the impact using weak java references in connections, but that will > introduce regressions in cases where references to the target objects > are not being kept. > > Given this happens with all connections, it seems that one must > explicitly dispose all toplevels. > > best regards, > Gunnar > > _______________________________________________ Qt-jambi-interest mailing list Qt-jambi-interest@trolltech.com http://lists.trolltech.com/mailman/listinfo/qt-jambi-interest