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]