SWT and memory management
by Kevin Dangoor
Pazu laments the pain of SWT. I was seriously considering Eclipse as an application framework, and SWT’s memory management needs were among the reasons that I opted for another path.
For those who haven’t looked at SWT, here’s the scoop: every SWT component (including ones that you write) have a dispose() method. If you make a panel that has several widgets (or even fonts and colors!) on it, you need to keep track of those and explicitly call their dispose() methods from your own dispose() method. If you don’t, you’ve got a memory leak… because SWT will never release the native widgets that it has allocated.
Why does SWT have this bit of nastiness and Swing does not? Because Swing doesn’t allocate native widgets. It draws all of its widgets, directly in Java code, using basic AWT calls.
If Java had real, reliable destructors this would not be a problem. But, alas…
SWT memory management isn’t exactly due the use of native widgets. AWT is also natively peered and don’t require explicit deallocation. SWT memory management is not a limitation, it’s just that SWT was designed this way.
Also, it’s not “even fonts and colors”. Fonts and colors are exactly the resources you should take note when writing a SWT application. When a Shell is disposed, it first disposes all it’s children, you don’t have to dispose each of them. However, fonts and colors aren’t child to any control, so those are the resources you need to explictly deallocate. Painful if not anything else.
But what pains me most about SWT is the lack of a proper model abstraction for UI components. Dealing only with ints and Strings is kinda awkward and restricted. What about a table where each cell (or each column) renders in a different manner? Not possible in SWT. Wanna laugh? What about a button with an icon *and* a label in it? Not possible in SWT.
If Java had destructors, then you would have to execute a “delete” statement where you currently have to make a call to the “dispose” method.
Destructors buy you nothing.
AWT is natively peered, but I don’t think it makes use of native “widgets”. As I understand it, and certainly correct me if I’m wrong, AWT uses simple graphics primitives. In SWT, you don’t need to dispose of points and rectanges because they’re just drawn, they’re not allocated.
So, since Swing draws the entire GUI, it’s not allocating native resources for its components. It’s simply using graphics primitives to draw its view.
I don’t think SWT has dispose() by choice.
I do agree with you Pazu, that the API for SWT’s widgets feels quite primitive to what Swing currently gives you. I was creating a special widget and needed to draw a polygon. Using Swing/Graphics2D I had access to a couple of convenient path drawing methods. Using SWT, I had to create an array of ints in the format [x,y,x,y,x,y,x,y]. Ick. I’m sure it’s more efficient, but it’s a lot less pleasant to program with.
As far as destructors go, the trick is that with destructors, *I* wouldn’t have to call dispose(). The Font class provided with SWT would have a destructor that disposes of its native resources, so I wouldn’t have to pay attention to it. The only time I would have to pay attention to the deallocation of native widgets is if I’m linking in my own.
Sure, having my own dispose() method gives me control over exactly when that Font is freed… but then using malloc in C gives me precise control over when the memory is allocated and freed. And that’s something I’d really rather not go back to.
What you need to realize is that SWT is a low-level API based on using as much of the native widget library as provided by the underlying OS, while Swing is a high-level API based on emulating GUI widgets (and based on the lower-level AWT). Eclipse provides JFace as a higher level abstraction layer over SWT.
Personally, I find SWT very straight-forward if you have a basic understanding of “real” OS-level GUI programming. The need to explicitly dispose of OS resources is rather natural.
And no, calling destructors doesn’t require an explicit “delete”. You just need to allocate the objects on the stack, which is quite common in C++ GUI programming.
Part of the reason that SWT and Swing get compared is that SWT “feels” considerably higher-level than AWT, because it provides much more powerful widgets. Of course, those widgets are generally implemented by the OS, and that’s certainly a difference. Comparing JFace with Swing may be a better comparison. I haven’t done a thorough review of what JFace provides on top of SWT.
As far as the need to dispose of resources being rather natural: it’s not natural for Java, which does all memory management for you with very few exceptions. I’d be curious to see how wxPython deals with this issue, because I’m doubtful that you’d have to manage resources this way in wxPython.
You also take into account the FontRegistry and ImageRegistry classes. These are in JFace and greatly simplify handling fonts and images. You create a registry and it will get disposed when the Display gets disposed. Easy. The only tricky bit is remembering to dispose of colours yourself.
The big problem with SWT and JFace is the lack of Models. Instead you have to build your own model-view-controller architecture on top of your own components if you want to do anything complex such as having a TableItem be a different colour depending on the state of the model.
Paul Hammant has a diagram about this explaining the different development costs over time using different GUI toolkits. http://paulhammant.com/blog//000083.html
Just out of interest, where in the JLS does it state that finalisers aren’t reliable? I guess a followup question is what do you mean by “reliable”?
I’ve worked with a number of languages with GC (including the BDW pessimistic GC for C/C++) and my understanding is that a reliable finaliser is one that is guaranteed to be invoked before the storage for the object is deallocated. I don’t see anything in the JLS that states that finalisers are unreliable according to this definition.
Of course there are other issues with finalisers such as ordering of invocation, elapsed time between an object becoming unreachable and it being finalised and deallocated etc., but those are relatively minor issues compared to the reliability issue (ie. unreliable finalisers are virtually useless, while slow or randomly ordered finalisers are not).
You’re right… generally finalizers will run. I’m not sure what exactly the JLS says, but here’s an article that talks about instances where the finalizer is not guaranteed to run:
http://www-106.ibm.com/developerworks/java/library/j-jtctips/j-jtc0319a.html
In the case of SWT, they may not have wanted to use finalizers to dispose of the native resources because it is unclear when exactly the resource will be freed and there could be issues with running out of memory unexpectedly as a result.
I don’t know if it’s possible to have C++ and Python style destructors if you use GC.