Hi, Firstly, I think that the Batik SVG toolkit is very good, and I have been very impressed with the overall quality and number of features implemented.
I am having trouble removing nodes from a SVG document that has been associated with a JSVGCanvas object. The problem is that although calling removeChild() stops the nodes from being displayed, it seems that the objects associated with that node are retained - preventing the removed nodes from being garbage collected. I am using Batik 1.5, the problem appears when using 1.4.1_02 and 1.4.1_03 of Java, and under Windows 2000 and KDE on linux. Hopefully this is due to a coding error on my part. There is a similiar message in the user archives at http://koala.ilog.fr/batik/mlists/batik-users/archives/msg02214.html. Although the message was replied to, I couldn't see anything to help solve my problem. I wrote a simple test program that built a SVG document that included a text element, associated it with a JSVGCanvas, then removed all child nodes of the document root. Using JProfiler, I found the following references to associated SVGOMTextElement (the format of this output is: name of the referant, number of references, total size of references): --- Incoming references before removeChild() class array content 6 784 field e of org.apache.batik.bridge.SVGTextElementBridge 1 40 field key of java.util.HashMap$Entry 1 24 field lastChild of org.apache.batik.dom.AbstractParentNode$ChildNodes 1 24 field nextSibling of org.apache.dom.svg.SVGOMRectElement 1 56 field ownerElement of org.apache.batik.dom.GenericAttr 2 80 field parentNode of org.apache.batik.dom.GenericText 1 40 field target of org.apache.batik.bridge.BridgeContext$EventListenerMememto 2 48 field target of org.apache.batik.dom.event.DOMMutationEvent 2 112 field this$0 of org.apache.batik.dom.AbstractParentNode$ChildNodes 1 24 field this$0 of org.apache.batik.dom.AbstractParentNode$ExtendedNamedNodeHashMap 1 24 field this$0 of org.apache.batik.dom.AbstractParentNode$ExtendedNamedNodeHashMap 1 24 field value of java.util.HashTable$Entry 1 24 field value of java.util.HashTable$Entry 1 24 --- Incoming references after removeChild() class array content 6 784 field e of org.apache.batik.bridge.SVGTextElementBridge 1 40 field ownerElement of org.apache.batik.dom.GenericAttr 2 80 field parentNode of org.apache.batik.dom.GenericText 1 40 field target of org.apache.batik.bridge.BridgeContext$EventListenerMememto 2 48 field this$0 of org.apache.batik.dom.AbstractParentNode$ChildNodes 1 24 field this$0 of org.apache.batik.dom.AbstractParentNode$ExtendedNamedNodeHashMap 1 24 field this$0 of org.apache.batik.dom.AbstractParentNode$ExtendedNamedNodeHashMap 1 24 field value of java.util.HashTable$Entry 1 24 These references are preventing the object from being garbage collected. After many additions and removals during the execution of my application, this causes a significant increase in the memory used. I have included the source code to the test program below. It is really just an amateurish mish-mash of the DOM API and JSVGCanvas tutorials. Any help as to how to prevent this object retention would be very much appreciated. -Daniel Spasojevic import java.awt.*; import java.awt.event.*; import java.io.*; import javax.swing.*; import org.apache.batik.dom.svg.SVGDOMImplementation; import org.w3c.dom.DOMImplementation; import org.apache.batik.swing.JSVGCanvas; import org.apache.batik.swing.svg.JSVGComponent; import org.apache.batik.swing.gvt.GVTTreeRendererAdapter; import org.apache.batik.swing.gvt.GVTTreeRendererEvent; import org.apache.batik.swing.svg.SVGDocumentLoaderAdapter; import org.apache.batik.swing.svg.SVGDocumentLoaderEvent; import org.apache.batik.swing.svg.GVTTreeBuilderAdapter; import org.apache.batik.swing.svg.GVTTreeBuilderEvent; import org.apache.batik.swing.svg.SVGLoadEventDispatcherAdapter; import org.apache.batik.swing.svg.SVGLoadEventDispatcherEvent; import org.w3c.dom.Element; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import org.w3c.dom.Document; import org.w3c.dom.svg.SVGDocument; public class SVGApplication { public static void main(String[] args) { JFrame f = new JFrame("Batik"); SVGApplication app = new SVGApplication(f); f.getContentPane().add(app.createComponents()); f.addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) { System.exit(0); } }); f.setSize(400, 400); f.setVisible(true); app.buildDoc(); } JFrame frame; JButton button = new JButton("Load..."); JLabel label = new JLabel(); JSVGCanvas svgCanvas = new JSVGCanvas(); Document svgDocument; Element topLevelElt; DOMImplementation sImpl; String svgNS; Thread processUserThread; public SVGApplication(JFrame f) { frame = f; } public JComponent createComponents() { final JPanel panel = new JPanel(new BorderLayout()); JPanel p = new JPanel(new FlowLayout(FlowLayout.LEFT)); p.add(button); p.add(label); panel.add("North", p); panel.add("Center", svgCanvas); // Set the button action. button.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent ae) { JFileChooser fc = new JFileChooser("."); int choice = fc.showOpenDialog(panel); if (choice == JFileChooser.APPROVE_OPTION) { File f = fc.getSelectedFile(); try { svgCanvas.setURI(f.toURL().toString()); } catch (IOException ex) { ex.printStackTrace(); } } } }); svgCanvas.setDocumentState(JSVGCanvas.ALWAYS_DYNAMIC); // Set the JSVGCanvas listeners. svgCanvas.addSVGDocumentLoaderListener(new SVGDocumentLoaderAdapter() { public void documentLoadingStarted(SVGDocumentLoaderEvent e) { label.setText("Document Loading..."); } public void documentLoadingCompleted(SVGDocumentLoaderEvent e) { label.setText("Document Loaded."); } }); svgCanvas.addGVTTreeBuilderListener(new GVTTreeBuilderAdapter() { public void gvtBuildStarted(GVTTreeBuilderEvent e) { label.setText("Build Started..."); } public void gvtBuildCompleted(GVTTreeBuilderEvent e) { label.setText("Build Done."); frame.pack(); } }); svgCanvas.addGVTTreeRendererListener(new GVTTreeRendererAdapter() { public void gvtRenderingPrepare(GVTTreeRendererEvent e) { label.setText("Rendering Started..."); } public void gvtRenderingCompleted(GVTTreeRendererEvent e) { label.setText("Render complete"); processUserThread = new Thread(new Runnable(){ public void run(){ System.err.println("Second thread"); doUserLoop(); } }); processUserThread.start(); } }); svgCanvas.addSVGLoadEventDispatcherListener(new SVGLoadEventDispatcherAdapter(){ public void svgLoadEventDispatchStarted(SVGLoadEventDispatcherEvent e){ label.setText("load event dispatch started"); } }); sImpl = SVGDOMImplementation.getDOMImplementation(); svgNS = SVGDOMImplementation.SVG_NAMESPACE_URI; return panel; } public void buildDoc(){ svgDocument = (SVGDocument)sImpl.createDocument(svgNS, "svg", null); topLevelElt = svgDocument.getDocumentElement(); topLevelElt.setAttributeNS(null, "width", "600"); topLevelElt.setAttributeNS(null, "height", "450"); // create the rectangle Element rectangle = svgDocument.createElementNS(svgNS, "rect"); rectangle.setAttributeNS(null, "x", "10"); rectangle.setAttributeNS(null, "y", "20"); rectangle.setAttributeNS(null, "width", "100"); rectangle.setAttributeNS(null, "height", "50"); rectangle.setAttributeNS(null, "style", "fill:red"); // attach the rectangle to the svg root element topLevelElt.appendChild(rectangle); svgCanvas.setSVGDocument((SVGDocument)svgDocument); } public void doUserLoop(){ BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in)); System.err.println("do user loop"); try{ addSomeText(); while(true){ String res = stdin.readLine(); if(res.equals("c")){ clearGraph(); } else { addSomeText(); } } } catch (IOException ioe){ System.err.println("IOException"); } } private void clearGraph(){ svgCanvas.getUpdateManager().getUpdateRunnableQueue().invokeLater(new Runnable(){ public void run(){ NodeList children = topLevelElt.getChildNodes(); if(children != null){ int numC = children.getLength(); System.err.println("num children: " + numC); for(int i = 0; i < numC; i++){ System.err.println(i); System.err.println("removing: " + children.item(0).getNodeName()); topLevelElt.removeChild(children.item(0)); System.err.println("removed"); } } } }); } private void addSomeText(){ svgCanvas.getUpdateManager().getUpdateRunnableQueue().invokeLater(new Runnable(){ public void run(){ System.err.println("Adding text"); Element newTextElt = svgDocument.createElementNS(svgNS, "text"); newTextElt.setAttributeNS(null, "x", "300"); newTextElt.setAttributeNS(null, "y", "200"); newTextElt.appendChild(svgDocument.createTextNode("Hello monkeys")); System.err.println("Appending"); topLevelElt.appendChild(newTextElt); System.err.println("Appended"); System.err.println("Added text"); } }); } } --------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
