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]