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]

Reply via email to