JDK-8187563 : sun.java2d.SunGraphics2D#dispose() method does not enough clear native memory
  • Type: Bug
  • Component: client-libs
  • Sub-Component: 2d
  • Affected Version: 7u151
  • Priority: P3
  • Status: Closed
  • Resolution: Not an Issue
  • OS: generic
  • CPU: x86
  • Submitted: 2017-09-14
  • Updated: 2018-04-30
  • Resolved: 2018-04-27
Related Reports
Relates :  
Relates :  
Description
C Heap size is increased when sun.java2d.SunGraphics2D instances are created/removed repeatedly and HotSpot does not execute Full GC. Then OutOfMemoryError or HotSpot crash may be happened depending on Java Heap Size on Windows 32bit environment especially.

C Heap increasing is also seen on other platform, for example Linux.

Reproduced on:
- 1.7.0_151:
  Java(TM) SE Runtime Environment (build 1.7.0_151-b33)
  Java HotSpot(TM) Client VM (build 24.151-b33, mixed mode, sharing)
- 1.8.0_144:
  Java(TM) SE Runtime Environment (build 1.8.0_144-b32)
  Java HotSpot(TM) Client VM (build 25.144-b32, mixed mode, sharing)
Comments
As outlined in comments above, this is not a bug. While BufferedImage instance isn't reclaimed by GC, its native resources cannot be disposed of. However, I submitted two follow-up bugs: ��� JDK-8201240: Improve releasing native resources of BufImgSurfaceData.ICMColorData ��� JDK-8201433: Fix potential crash in BufImg_SetupICM
27-04-2018

Upon further investigation, it proved the problem is not in SunGraphics2D.dispose(). The problem is that the test case creates a new BufferedImage at each iteration. Each instance of BufferedImage is used once for drawing and then it's left unreferenced. Objects of type sun.awt.image.BufImgSurfaceData$ICMColorData are associated with native surfaces which represent BufferedImage. Neither the surface nor ICMColorData can be disposed of while Java object for BufferedImage isn't reclaimed. ------- Graphics object is needed to draw to BufferedImage. When you call Graphics.dispose(), it releases structures that are used for drawing. BufferedImage is still valid and usable. You blit its bits to another Image. You can draw to it later. It is only when BufferedImage object is reclaimed, its native resources are also reclaimed. That's why you need Garbage Collector. Otherwise either side of BufferedImage is preserved: Java object and its native counterpart. ------- The code can be modified so that one BufferedImage is re-used, and the problem goes away. Of course, in this case the image in BufferedImage must be cleared before drawing a new one.
27-04-2018

The test application is run with large Java heap: -Xms1280m -Xmx1280m In 32 bit JRE, it leaves not much memory for native allocations. Large Java heap ensures GC is not triggered. When Java objects are garbage collected, the corresponding native resources are also freed. So in this case, reducing the Java heap helps, and the test case completes successfully.
27-04-2018