Can boehm-gc be made to finalize more promptly?

Oscar Pearce oscar@pearceenterprises.com
Thu Jan 16 06:39:00 GMT 2003


Upon reading Sun's Javadoc for java.awt.Graphics, it looks like the
right thing to do would be for java.awt.Component.processPaintEvent to
call gfx.dispose() after it's done with the Graphics object.  The
Javadoc says that the system will call dispose() on the Graphics objects
passed to paint or update, and guess what, we're the system in this case
:-).

That's not to say that it couldn't be solved with some GC hackery, but
this seems a lot simpler.

[One of my gripes with Java is that it doesn't have guaranteed
destructors like C++, so you're left with methods like dispose and
try/finally blocks to make sure external resources get cleaned up.  Of
course, after programming in Java for the last five years, I've gotten
used to it.  I still don't like it, though.]

I've attached the trivial patch for java.awt.Component.  It might even
compile.

On Wed, 2003-01-15 at 20:26, Scott Gilbertson wrote:
> Further to my "Out of Memory" crash post, I'm now pretty sure I know, in
> general terms, why my program is crashing.
> 
> It seems like the fundamental problem is that the native xlib code allocates
> a lot of memory, and the associated java objects don't get finalized right
> away.  That's presumably because the java parts of those objects are small,
> so the garbage collector is in no great hurry to clear them off
> (particularly if several of them are in the same memory page, and only some
> are collectable).  The total memory used by the program therefore grows
> quickly, while the garbage collector thinks it's growing slowly.  The
> garbage collector thinks there's lots of memory left, right up to the point
> where the memory runs out.
> 
> For example, every time an awt component gets a paint event, it calls
> getGraphics on the nearest heavyweight.  That function ultimately calls
> XCanvasPeer.getGraphics, which creates, among other things, a new XGraphics.
> Somewhere in there, a new gnu.gcj.xlib.GC is created.  The associated native
> library (natGC.cc) calls XCreateGC (which allocates some memory) when a GC
> is constructed, and XFreeGC when the GC is finalized.  I instrumented the
> constructor and finalize for xlib.GC, and did a whole bunch of repaints in
> my program.  The program crashed, having constructed 97 GC objects and
> having finalized none of them, even though each one was no longer needed
> once its paint event was finished.  Calling System.gc very frequently
> prevents the crash, but it makes the program unusably slow.
> 
> Is there a way to get the GC to finalize "small" java objects which have
> large natively-allocated blocks more promptly?
> 
> How about a way to code the xlib native stuff which helps the garbage
> collector to tell when too much memory is in use?
> 
> Perhaps we could do gfx.finalize at the end of
> java.awt.Component.processPaintEvent, and write the finalizers so each class
> calls finalize for every object it has constructed or cloned (i.e. make them
> look kind of like C++ destructors).  This way all the natively-allocated
> stuff would be deallocated each time we finish processPaintEvent.  The java
> part would hang around on the heap until the garbage collector found it.
> We'd only do this for things like xlib that have the potential to allocate a
> lot of memory from native code.  Comments on that?
-------------- next part --------------
--- Component.java.orig	2003-01-16 00:29:55.000000000 -0600
+++ Component.java	2003-01-16 00:31:52.000000000 -0600
@@ -4168,19 +4168,26 @@
       return;
 
     Graphics gfx = getGraphics();
-    Shape clip = event.getUpdateRect();
-    gfx.setClip(clip);
+    try
+      {
+      Shape clip = event.getUpdateRect();
+      gfx.setClip(clip);
 
-    switch (event.id)
+      switch (event.id)
+        {
+        case PaintEvent.PAINT:
+          paint(gfx);
+          break;
+        case PaintEvent.UPDATE:
+          update(gfx);
+          break;
+        default:
+          throw new IllegalArgumentException("unknown paint event");
+        }
+      }
+    finally
       {
-      case PaintEvent.PAINT:
-        paint(gfx);
-        break;
-      case PaintEvent.UPDATE:
-        update(gfx);
-        break;
-      default:
-        throw new IllegalArgumentException("unknown paint event");
+      gfx.dispose();
       }
   }
 


More information about the Java mailing list