deweese     2003/06/19 04:51:35

  Modified:    sources/org/apache/batik/bridge BridgeContext.java
               sources/org/apache/batik/ext/awt/image GraphicsUtil.java
               sources/org/apache/batik/ext/awt/image/rendered TileMap.java
               sources/org/apache/batik/gvt/font AWTFontFamily.java
               sources/org/apache/batik/util SoftReferenceCache.java
  Added:       sources/org/apache/batik/util CleanerThread.java
  Log:
  Fixed memory leak with text and anything else that was storing event listeners
  in the BridgeContext.
  
  Revision  Changes    Path
  1.63      +49 -10    xml-batik/sources/org/apache/batik/bridge/BridgeContext.java
  
  Index: BridgeContext.java
  ===================================================================
  RCS file: /home/cvs/xml-batik/sources/org/apache/batik/bridge/BridgeContext.java,v
  retrieving revision 1.62
  retrieving revision 1.63
  diff -u -r1.62 -r1.63
  --- BridgeContext.java        11 Jun 2003 22:07:24 -0000      1.62
  +++ BridgeContext.java        19 Jun 2003 11:51:34 -0000      1.63
  @@ -12,6 +12,7 @@
   import java.awt.geom.Dimension2D;
   import java.io.IOException;
   import java.io.InterruptedIOException;
  +import java.lang.ref.SoftReference;
   import java.net.MalformedURLException;
   import java.net.URL;
   import java.util.HashMap;
  @@ -37,6 +38,7 @@
   import org.apache.batik.script.Interpreter;
   import org.apache.batik.script.InterpreterPool;
   import org.apache.batik.util.CSSConstants;
  +import org.apache.batik.util.CleanerThread;
   import org.apache.batik.util.ParsedURL;
   import org.apache.batik.util.SVGConstants;
   import org.apache.batik.util.Service;
  @@ -883,7 +885,24 @@
                                         String s,
                                         EventListener l,
                                         boolean b) {
  -        eventListenerList.add(new EventListenerMememto(t, s, l, b));
  +        eventListenerList.add(new EventListenerMememto(t, s, l, b, this));
  +    }
  +
  +    public static class SoftReferenceMememto 
  +        extends CleanerThread.SoftReferenceCleared {
  +        Object mememto;
  +        List   list;
  +        SoftReferenceMememto(Object ref, Object mememto, List list) {
  +            super(ref);
  +            this.mememto = mememto;
  +            this.list    = list;
  +        }
  +
  +        public void cleared() {
  +            list.remove(mememto);
  +            mememto = null;
  +            list    = null;
  +        }
       }
   
       /**
  @@ -891,22 +910,38 @@
        */
       protected static class EventListenerMememto {
   
  -        public EventTarget target;
  -        public EventListener listener;
  +        public SoftReference target; // Soft ref to EventTarget
  +        public SoftReference listener; // Soft ref to EventListener 
           public boolean useCapture;
           public String eventType;
   
           public EventListenerMememto(EventTarget t, 
                                       String s, 
                                       EventListener l, 
  -                                    boolean b) {
  -            target = t;
  +                                    boolean b,
  +                                    BridgeContext ctx) {
  +            List list = ctx.eventListenerList;
  +            target = new SoftReferenceMememto(t, this, list);
  +            listener = new SoftReferenceMememto(l, this, list);
               eventType = s;
  -            listener = l;
               useCapture = b;
           }
  +
  +        public EventListener getListener() {
  +            return (EventListener)listener.get();
  +        }
  +        public EventTarget getTarget() {
  +            return (EventTarget)target.get();
  +        }
  +        public boolean getUseCapture() {
  +            return useCapture;
  +        }
  +        public String getEventType() {
  +            return eventType;
  +        }
       }
   
  +
       /**
        * Disposes this BridgeContext.
        */
  @@ -916,9 +951,13 @@
           Iterator iter = eventListenerList.iterator();
           while (iter.hasNext()) {
               EventListenerMememto m = (EventListenerMememto)iter.next();
  -            m.target.removeEventListener(m.eventType,
  -                                         m.listener,
  -                                         m.useCapture);
  +            EventTarget   et = m.getTarget();
  +            EventListener el = m.getListener();
  +            boolean       uc = m.getUseCapture();
  +            String        t  = m.getEventType();
  +            if ((et == null) || (el == null) || (t == null))
  +                continue;
  +            et.removeEventListener(t, el, uc);
           }
   
           EventTarget evtTarget = (EventTarget)document;
  
  
  
  1.29      +2 -3      
xml-batik/sources/org/apache/batik/ext/awt/image/GraphicsUtil.java
  
  Index: GraphicsUtil.java
  ===================================================================
  RCS file: 
/home/cvs/xml-batik/sources/org/apache/batik/ext/awt/image/GraphicsUtil.java,v
  retrieving revision 1.28
  retrieving revision 1.29
  diff -u -r1.28 -r1.29
  --- GraphicsUtil.java 6 Jun 2003 00:14:25 -0000       1.28
  +++ GraphicsUtil.java 19 Jun 2003 11:51:34 -0000      1.29
  @@ -251,8 +251,7 @@
                        0, 0, null);
                   
                   BufferedImage bi = new BufferedImage
  -                    (srcCM, wr, 
  -                     srcCM.isAlphaPremultiplied(), null);
  +                    (srcCM, wr, srcCM.isAlphaPremultiplied(), null);
                   
                   // Any of the drawImage calls that take an
                   // Affine are prone to the 'CGGStackRestore: gstack 
  
  
  
  1.10      +14 -42    
xml-batik/sources/org/apache/batik/ext/awt/image/rendered/TileMap.java
  
  Index: TileMap.java
  ===================================================================
  RCS file: 
/home/cvs/xml-batik/sources/org/apache/batik/ext/awt/image/rendered/TileMap.java,v
  retrieving revision 1.9
  retrieving revision 1.10
  diff -u -r1.9 -r1.10
  --- TileMap.java      11 Apr 2003 13:58:01 -0000      1.9
  +++ TileMap.java      19 Jun 2003 11:51:35 -0000      1.10
  @@ -10,23 +10,31 @@
   
   import java.awt.Point;
   import java.awt.image.Raster;
  -import java.lang.ref.Reference;
  -import java.lang.ref.ReferenceQueue;
   import java.lang.ref.SoftReference;
   import java.util.HashMap;
   
  +import org.apache.batik.util.CleanerThread;
  +
   public class TileMap implements TileStore {
       private static final boolean DEBUG = false;
       private static final boolean COUNT = false;              
   
  -    private static ReferenceQueue queue = new ReferenceQueue();
  -
  -    private static HashMap items  =new HashMap();
       private HashMap rasters=new HashMap();
   
       static class TileMapLRUMember extends TileLRUMember {
           public Point   pt;
           public SoftReference parent;
  +
  +        class RasterSoftRef extends CleanerThread.SoftReferenceCleared {
  +            RasterSoftRef(Object o) { super(o); }
  +            public void cleared() {
  +                if (DEBUG) System.err.println("Cleaned: " + this);
  +                TileMap tm = (TileMap)parent.get();
  +                if (tm != null)
  +                    tm.rasters.remove(pt);
  +            }
  +        };
  +
           TileMapLRUMember(TileMap parent, Point pt, Raster ras) {
               super(ras);
               this.parent = new SoftReference(parent);
  @@ -35,12 +43,7 @@
   
           public void setRaster(Raster ras) {
               hRaster = ras;
  -            synchronized (items) {
  -                if (wRaster != null)
  -                    items.remove(wRaster);
  -                wRaster = new SoftReference(ras, queue);
  -                items.put(wRaster, this);
  -            }
  +            wRaster = new RasterSoftRef(ras);
           }
       }
   
  @@ -135,35 +138,4 @@
   
       static int requests;
       static int misses;
  -
  -    static Thread cleanup;
  -
  -    static {
  -        cleanup = new Thread() {
  -                public void run() {
  -                    while(true) {
  -                        Reference ref;
  -
  -                        try {
  -                            ref = queue.remove();
  -                        } catch (InterruptedException ie) {
  -                            continue;
  -                        }
  -                        synchronized (items) {
  -                            Object o = items.remove(ref);
  -                            if (DEBUG) System.out.println("Cleaning: " + o);
  -                            if (o == null) continue;
  -                        
  -                            TileMapLRUMember item = (TileMapLRUMember)o;
  -                         TileMap parent = (TileMap)item.parent.get();
  -                         if (parent != null)
  -                             parent.rasters.remove(item.pt);
  -                        }
  -                    }
  -                }
  -            };
  -        cleanup.setDaemon(true);
  -        cleanup.start();
  -    }
  -
   }
  
  
  
  1.4       +4 -1      xml-batik/sources/org/apache/batik/gvt/font/AWTFontFamily.java
  
  Index: AWTFontFamily.java
  ===================================================================
  RCS file: /home/cvs/xml-batik/sources/org/apache/batik/gvt/font/AWTFontFamily.java,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -r1.3 -r1.4
  --- AWTFontFamily.java        11 Apr 2003 13:58:43 -0000      1.3
  +++ AWTFontFamily.java        19 Jun 2003 11:51:35 -0000      1.4
  @@ -11,6 +11,7 @@
   import java.awt.font.TextAttribute;
   import java.text.AttributedCharacterIterator;
   import java.util.HashMap;
  +import org.apache.batik.gvt.text.GVTAttributedCharacterIterator;
   
   /**
    * A font family class for AWT fonts.
  @@ -48,9 +49,11 @@
        *             the derived font.  
        */
       public GVTFont deriveFont(float size, AttributedCharacterIterator aci) {
  +
           HashMap fontAttributes = new HashMap(aci.getAttributes());
           fontAttributes.put(TextAttribute.SIZE, new Float(size));
           fontAttributes.put(TextAttribute.FAMILY, familyName);
  +        
fontAttributes.remove(GVTAttributedCharacterIterator.TextAttribute.TEXT_COMPOUND_DELIMITER);
           return new AWTGVTFont(fontAttributes);
       }
   
  
  
  
  1.5       +14 -55    xml-batik/sources/org/apache/batik/util/SoftReferenceCache.java
  
  Index: SoftReferenceCache.java
  ===================================================================
  RCS file: /home/cvs/xml-batik/sources/org/apache/batik/util/SoftReferenceCache.java,v
  retrieving revision 1.4
  retrieving revision 1.5
  diff -u -r1.4 -r1.5
  --- SoftReferenceCache.java   11 Apr 2003 13:59:29 -0000      1.4
  +++ SoftReferenceCache.java   19 Jun 2003 11:51:35 -0000      1.5
  @@ -9,7 +9,6 @@
   package org.apache.batik.util;
   
   import java.lang.ref.Reference;
  -import java.lang.ref.ReferenceQueue;
   import java.lang.ref.SoftReference;
   import java.util.HashMap;
   
  @@ -149,69 +148,29 @@
        */
       protected final synchronized void putImpl(Object key, Object object) {
           if (map.containsKey(key)) {
  -            SoftReference ref = new SoftReference(object, queue);
  +            SoftReference ref = new SoftRefKey(object, key);
               map.put(key, ref);
  -            synchronized (refMap) {
  -                refMap.put(ref, new Info(key, this));
  -            }
               this.notifyAll();
           }
       }
   
  -    static class Info {
  +    class SoftRefKey extends CleanerThread.SoftReferenceCleared {
           Object key;
  -        SoftReference cacheRef;
  -        public Info(Object key,
  -                    SoftReferenceCache cache) {
  +        public SoftRefKey(Object o, Object key) {
  +            super(o);
               this.key = key;
  -            this.cacheRef = new SoftReference(cache);
           }
   
  -        public Object getKey() { return key; }
  -
  -        public SoftReferenceCache getCache() { 
  -            return (SoftReferenceCache)cacheRef.get(); 
  +        public void cleared() {
  +            SoftReferenceCache cache = SoftReferenceCache.this;
  +            if (cache == null) return; // Can't really happen.
  +            synchronized (cache) {
  +                Object o = cache.map.remove(key);
  +                if (this != o)
  +                    // Must not have been ours put it back...
  +                    // Can happen if a clear is done.
  +                    cache.map.put(key, o);
  +            }
           }
       }
  -
  -    private static HashMap        refMap = new HashMap();
  -    private static ReferenceQueue queue = new ReferenceQueue();
  -    private static Thread cleanup;
  -
  -    static {
  -        cleanup = new Thread() {
  -                public void run() {
  -                    while(true) {
  -                        Reference ref;
  -                        try {
  -                            ref = queue.remove();
  -                        } catch (InterruptedException ie) {
  -                            continue;
  -                        }
  -
  -                        Object o;
  -                        synchronized (refMap) {
  -                            o = refMap.remove(ref);
  -                        }
  -
  -                        // System.out.println("Cleaning: " + o);
  -                        if (o == null) continue;
  -                        Info info = (Info)o;
  -                        SoftReferenceCache cache = info.getCache();
  -                        if (cache == null) continue;
  -                        synchronized (cache) {
  -                            o = cache.map.remove(info.getKey());
  -                            if (ref != o)
  -                                // Must not have been ours put it back...
  -                                // Can happen if a clear is done.
  -                                cache.map.put(info.getKey(), o);
  -                        }
  -                    }
  -                }
  -            };
  -        cleanup.setDaemon(true);
  -        cleanup.start();
  -    }
  -
  -
   }
  
  
  
  1.1                  xml-batik/sources/org/apache/batik/util/CleanerThread.java
  
  Index: CleanerThread.java
  ===================================================================
  /*****************************************************************************
   * Copyright (C) The Apache Software Foundation. All rights reserved.        *
   * ------------------------------------------------------------------------- *
   * This software is published under the terms of the Apache Software License *
   * version 1.1, a copy of which has been included with this distribution in  *
   * the LICENSE file.                                                         *
   *****************************************************************************/
  
  package org.apache.batik.util;
  
  import java.lang.ref.Reference;
  import java.lang.ref.ReferenceQueue;
  import java.lang.ref.SoftReference;
  import java.lang.ref.WeakReference;
  import java.lang.ref.PhantomReference;
  
  /**
   * One line Class Desc
   *
   * Complete Class Desc
   *
   * @author <a href="mailto:[EMAIL PROTECTED]>l449433</a>
   * @version $Id: CleanerThread.java,v 1.1 2003/06/19 11:51:35 deweese Exp $
   */
  public class CleanerThread extends Thread {
  
      static ReferenceQueue queue = null;
      static CleanerThread  thread = null;
  
      public static ReferenceQueue getReferenceQueue() { 
          if (queue != null) 
              return queue;
          
          queue = new ReferenceQueue();
          thread = new CleanerThread();
          return queue; 
      }
  
      /**
       * If objects registered with the reference queue associated with
       * this class implement this interface then the 'cleared' method
       * will be called when the reference is queued.
       */
      public static interface ReferenceCleared {
          /* Called when the reference is cleared */
          public void cleared();
      }
  
      /**
       * A SoftReference subclass that automatically registers with 
       * the cleaner ReferenceQueue.
       */
      public static abstract class SoftReferenceCleared extends SoftReference 
        implements ReferenceCleared {
          public SoftReferenceCleared(Object o) {
              super (o, CleanerThread.getReferenceQueue());
          }
      }
  
      /**
       * A WeakReference subclass that automatically registers with 
       * the cleaner ReferenceQueue.
       */
      public static abstract class WeakReferenceCleared extends WeakReference 
        implements ReferenceCleared {
          public WeakReferenceCleared(Object o) {
              super (o, CleanerThread.getReferenceQueue());
          }
      }
  
      /**
       * A PhantomReference subclass that automatically registers with 
       * the cleaner ReferenceQueue.
       */
      public static abstract class PhantomReferenceCleared 
          extends PhantomReference 
          implements ReferenceCleared {
          public PhantomReferenceCleared(Object o) {
              super (o, CleanerThread.getReferenceQueue());
          }
      }
              
      protected CleanerThread() {
          setDaemon(true);
          start();
      }
  
      public void run() {
          while(true) {
              Reference ref;
              try {
                  ref = queue.remove();
                  // System.err.println("Cleaned: " + ref);
              } catch (InterruptedException ie) {
                  continue;
              }
  
              if (ref instanceof ReferenceCleared) {
                  ReferenceCleared rc = (ReferenceCleared)ref;
                  rc.cleared();
              }
          }
      }
  };
  
  
  

---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to