When to call Graphics.dispose()

How do you know when you are supposed to call dispose() on a Graphics object? I’ve seen code in examples, even in Sun’s tutorials, where I’ve expected that dispose() should be called but it isn’t. In the same way I’ve seen code call dispose() when I didn’t think it was needed.

E.g. in your paint(Graphics g) method you would typically not call dispose on the Graphics passed in, right?
But if you get the Graphics object for a buffered image you should call dispose() when you are done drawing to it, right?

Can somebody clarify exactly when it is needed, and when it isn’t? And what harm it might do to call it when not needed, or not call it when needed.

Just guessing here, but you should only call dispose() on a graphics context that you have ownership of?

In the case of paint(Graphics g):

You were passed the graphics context from the infrastructure around you. It will clear up whatever needs clearing up. Its not right for you to dispose() it, its not yours two dispose. Not to mention, it might be passed to someone else subsequently and you disposing it might screw things up.

In the case of getGraphics() from BufferedImge:

You own the graphics context. You know when its finished being used. You can therefore choose when is the correct moment to dispose() it. That said, once you have called dispose(), don’t attempt to use it again :wink:

Like I said, I don’t know for sure… but ownership would seem to be the key.

Kev

EDIT: not sure this helps any, maybe it only clarifies the question? (I hope)

Yes… that is exactly what I assumed. However I have seen cases of calls to getGraphics() or createGraphics() not matched with a dispose() and was wondering if that was a bug, a leak of some sort, or if there were cases when it simply wasn’t needed.

For instance when createGraphics is called on a off-screen BufferedImage, perhaps there are no resources that need disposing, which is different from the case of getting the graphics context for a on-screen component. In the BufferedImage case I would figure it is still correct to call dispose(), but maybe it doesn’t actually do much?

For example look at http://developer.java.sun.com/developer/JDCTechTips/2002/tt0618.html#tip2
createGraphics() is called on BufferedImages with no call to Graphics.dispose().

yeah, its another grey area that probably needs some refining from Sun.

Calling dispose() on Graphics objects obtained from bufferStrategy.getDrawGraphics() BEFORE calling bufferStrategy.show() is probably a good idea. ;D

The rest probably don’t make much of a difference… probably :wink:

I’ve never noticed any difference in speed, resource use, smoothness, etc when I do or don’t call dispose(). I’ve never been convinced it’s a mission critical method call. Although I usually do call it after grabbing and using my own Graphics from BufferStrategy.getDrawGraphics() or BufferedImage.createGraphics().

And doesn’t not knowing if you should or should not call a public method on an object kinda go against the whole OO paradigm? If an object gets passed to you that has functionality that you definitely should not invoke, then that functionality shouldn’t be public.

Thats a very good point!

To be fair it would be difficult to solve the problem of having the object providing the Graphics manage the dispose() stuff on its own.

Obviously dispose() should be called in some cases or it would not have been exposed. I just wish those cases were documented.

For what it’s worth, I’ve never called dispose() on a Dialog or Frame and apparently you are supposed to do that too. I guess the native window structures live in memory as long as you haven’t disposed? (I assume there is a finalizer on the Window object to handle this as well? I suppose I could check myself… but I’m feeling lazy :P)

I never called dispose() on any AWT stuff either!

Until I started using fullscreen… now I use it all the time.

In my experience System.exit() causes serious problems when in fullscreen &| using bufferstrategy :-/
(fullscreen often doesn’t return the resolution, and bufferstrategy sometimes doesn’t de-allocate vram thats its taken for back buffers - hence the app. will mess up after 10-20 runs)

Calling Graphics.dispose() is desireable, but not required (which is a pity). After a graphics object is disposed, any rendering to it will be a no-op. You won’t leak any resources if you don’t, though.

You’re supposed to call dispose only for the objects you’ve created yourself.

It is a good idea to call Window/Frame.dispose() when you’re done with the object, because otherwise your app will hang forever (unless you call System.exit explicitly), because AWT Toolkit thread will be running until all windows are disposed of.

Slightly related to this topic.

If you create a JDialog or JWindow using the null parent Constructor; a shared hidden anonymous Frame is created to act as the parent.

However, i’ve yet to find a way of disposing of this Frame. (Hence can’t get the AWT Thread to terminate)

The offending code can be found in SwingUtilities.java Line 1615.

    static Frame getSharedOwnerFrame() throws HeadlessException {
        Frame sharedOwnerFrame =
            (Frame)SwingUtilities.appContextGet(sharedOwnerFrameKey);
        if (sharedOwnerFrame == null) {
            sharedOwnerFrame = new Frame() {
                public void show() {
                    // This frame can never be shown
                }
                public synchronized void dispose() {
                    try {
                        getToolkit().getSystemEventQueue();
                        super.dispose();
                    } catch (Exception e) {
                        // untrusted code not allowed to dispose
                    }
                }
            };
            SwingUtilities.appContextPut(sharedOwnerFrameKey,
                                         sharedOwnerFrame);
        }
        return sharedOwnerFrame;
    }

Is there a way of disposing of this Frame once it has been created?

[quote]It is a good idea to call Window/Frame.dispose() when you’re done with the object, because otherwise your app will hang forever…
[/quote]
Thanks Trembovetski, I knew you would have the answers :).

Does the above statement apply to JDialogs? And if I don’t call dispose on my JDialog will it at least ‘dispose’ via a finalizer so the AWT thread can die (assuming the finalizer gets a chance to run)?

I wonder if dispose() is not required and you won’t leak resources if you don’t call it… what exactly does it do? It sounds like this is a place were platform specific problems could show up. I.e. are JRE implementers allowed to make objects leak resources if dispose is not called?

Until you call dispose on a Frame the operating system is considered to have a reference to the Frame which prevents it being collected. In 1.4 and later this also prevents the program from exiting unless the brute force System.exit method is used.
There are also likely to be system resource leaks, but on NT this won’t be noticeable (unlike Windows 9X where certain system resources really are limited). Any Graphics object which has an underlying system HDC or equivalent should be disposed (by you if you created it or by the libraries in the case of paint methods). Again Windows NT can tolerate leaking a large number of device contexts but Windows 9X can not.
There are probably no system resources involved in the Graphics created from a BufferedImage, so the dispose is likely to be an empty method. You should still call it and leave the JIT to eliminate the redundant call.

So the rule is simple: call dispose on all Graphics objects which you create and leave the JIT to eliminate the calls which are in fact redundant.

Yeah, that appears to be the right thing to do. Now someone tell Sun to update their examples and tutorials so they don’t encourage people to ignore dispose() :slight_smile:

In our current implementation the Graphics object (at least, in Sun’s jdk) doesn’t hold any native resources, it’s a lightweight object which just basically represents current rendering state/attributes.

The native resoucres are associated with the destination surface (component on the screen, or an image). Graphics object has a link to the surface it’s associated with, so, for example, if you hold on to the graphics, but let go of the image, the latter won’t be collected. One of the things Graphics.dispose does is it nulls out the link.
It also makes sure that any further rendering to this graphics object are no-ops.

By disposing of the graphics when you’re done you’re closing the door on stuff like rendering to an obsolete graphics object (even though we handle that for you), or any multithreading issues which may arise (Graphics is not thread-safe), if other thread renders to the graphics object you think you’re done with.

As for Window.dispose (and any of it’s descendants, basically any toplevel components), Mark nailed it.

Ah, ok, so the finalizer can’t call dispose because the whole point is that the object still lives via the reference the native code is holding. I have some leaks to patch… :slight_smile:

If you feel motivated, please flush out: http://wiki.java.net/bin/view/Games/HowToCallGraphicsDispose with the concise knowledge of this thread.

… and if you hunger for more, give: http://wiki.java.net/bin/view/Games/WebHome some love.

BTW, it’s generally not a good idea to use finalizers to dispose of resourses. It takes two full gc cycles to get rid of an object with a finalizer: one to put it into an old gen, and another one to run finalizer and get rid of the object.

I’d suggest using Weak/PhantomReferences with ReferenceQueues instead.

Our gc usage pattern improved a lot once we stopped using finalizers.