smwikipedia
smwikipedia

Reputation: 64453

Should I explicitly dispose the Graphics object?

The javadoc said:

For efficiency, programmers should call dispose when finished using a Graphics object only if it was created directly from a component or another Graphics object.

So in the following code, should I call graphics.dispose() before returning? Or, can I?

{  ...  
BufferedImage result = new BufferedImage(toWidth, toHeight, BufferedImage.TYPE_INT_RGB);  

java.awt.Graphics graphics=result.getGraphics();

graphics.drawImage(im.getScaledInstance(toWidth, toHeight, java.awt.Image.SCALE_SMOOTH), 0, 0, null);  

return result;  
}

The BufferedImage result is returned and used elsewhere.

Upvotes: 6

Views: 4501

Answers (3)

Marco13
Marco13

Reputation: 54719

The Graphics object can be disposed and should be disposed.

The getGraphics call of BufferedImage internally delegates to createGraphics, so there is no difference. The createGraphics call eventually delegates to the respective GraphicsEnvironment implementation, where (for the SunGraphicsEnvironment) it creates a new instance of a SunGraphics2D.

Finally, the dispose method of SunGraphics2D says the following:

  /**
   * This object has no resources to dispose of per se, but the
   * doc comments for the base method in java.awt.Graphics imply
   * that this object will not be useable after it is disposed.
   * So, we sabotage the object to prevent further use to prevent
   * developers from relying on behavior that may not work on
   * other, less forgiving, VMs that really need to dispose of
   * resources.
   */
  public void dispose() {
      surfaceData = NullSurfaceData.theInstance;
      invalidatePipe();
  }

which also gives a justification of why dispose indeed should be called (even if it is not strictly necessary in the default implementations)

Upvotes: 9

Loki
Loki

Reputation: 4130

public class Main{

    public static void main(String[] args) {
        BufferedImage img = get();

        Graphics g = img.getGraphics();

        //g.drawOval(5, 5, 5, 5); //this statement will work (you'll see the cirle)

        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        try {
            ImageIO.write( img, "jpg", baos );

            baos.flush();
            byte[] imageInByte = baos.toByteArray();
            baos.close();

            Files.write(Paths.get("test2.png"), imageInByte);
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }


    public static BufferedImage get(){
        BufferedImage res = new BufferedImage(50, 50, BufferedImage.TYPE_INT_ARGB);

        Graphics g = res.getGraphics();

        g.drawRect(0, 0, 20, 20);

        g.dispose();

        g.drawOval(5, 5, 5, 5); //this statement won't work, you'll only see the rect

        return res;
    }


}

As you can see, you can savely (and should) dispose the graphics in your method.

You can't use the graphics object in the method afterwards, so when you run the code, there won't be a circle in the picture. But if you comment out g.drawOval(5,5,5,5) in the method, but comment in the same statement in the main-Method, you will see a circle. So you can use it afterwards.

Upvotes: 1

Sergiy Medvynskyy
Sergiy Medvynskyy

Reputation: 11327

Because due to JavaDoc getGpahics() method forwards to createGraphics() you should dispose the Graphics object at the end of your method.

Upvotes: 0

Related Questions