Menu

Heap Error - how to remove graph from memory?

Help
Martina
2007-08-26
2013-05-29
1 2 > >> (Page 1 of 2)
  • Martina

    Martina - 2007-08-26

    Hello Prefuse people,

    I am visualizing moderate sized graphs (about 500 nodes max) via prefuse, using a graph with a NodeLinkTreeLayout.
    However I need to delete old graphs and create new ones instead lots of times due to my app.

    I keep receiving a Java Heap out of memory error after having created a new graph about 2 times. Due to the output from some profiling tool I guess, the old graphs aren't deleted, when I created new ones.

    The point is: I have NO idea HOW to delete some graph properly so it doesent't keept stuck in the memory...

    To point it out:
    On clicking certain areas on another (not prefuse) graph, I create a window, which contains the prefuse graph. After this window is closed, the user can click again on anothe r regions of the non-prefuse-grasph and should receive a completely new graph. The old one has to be destroyed and removed from memory, and this is my problem.

    Anyone here, who can point out to me, WHAT to do to destroy a prefuse graph and get it completely out of my apps memory?

    Any help would be greatly appreciated!

    Thanks so much,
    Martina!

     
    • Björn Kruse

      Björn Kruse - 2007-08-28

      Try Visualization.reset() and graph.clear() (or any other tupleset.clear()). I haven't tried that, but is the most I can give you...

      regards, Björn

       
    • Martina

      Martina - 2007-08-28

      I tried that already, but it doesn't seem to work, memory's still full and its definitely due to the prefuse graph :(

      Could anyone, as an alternative point me out, how to create just one graph and reset it completely? this way i wouldn't have to completely remove it, just remove every node and every ege and fill in the new ones...

      Thanks in advance
      Martina

       
    • Martina

      Martina - 2007-08-28

      Well. I tried to Visualization.reset() and graph.clear() once again, just to be sure, I am not missing anything. Unfortunately it didn't work again. The first and the second graph creation are working fine, but by then the memory is full. So I receive a "heap error" at creating the graph the third time.

      I'm kind of desperate now, cause the prefuse graphs are really nice, and I'd really like to use them in my project - but I need to create new graphs very often or at least reset the old one very often without getting heap memory errors ...

      thanks so much
      Martina

       
      • MartienNL

        MartienNL - 2007-08-28

        I think you have some reference somewhere to the graph its data. So I assume that Java still holds the graph because of that reference. Take a look at your code and try to find it.
        For me it works with finally the

        treeview.setVisualization(null);

        Before that I cleanup a lot of references, e.g. to the searchpanel (yes, that also points to the data) and remove some special group also.

        Hope this helps.

        Martien

         
    • Martina

      Martina - 2007-08-28

      Hell Martien

      thank you so far. I don't have any kind of searchpanel or such thinks, i just draw my graph into a scrollpanes viewport and display it. So I'll see if there are references leftover anywhere...

      One further question: my mentioned scrollpane is displayed within an ordinary JFrame. On clicking the X, the JFrame is closed(as always) - I thought that Java would clean up any stuff related to this frame afterwards (like the JFRame itself, the ScrollPane etc?) - so there shouldn't be any more reference to the graph... I don't see it... I am kind of newbie with java and the garbage collection stuff, and would appreciate any further hints of what to do...

       
    • Martina

      Martina - 2007-08-28

      OK, sorry, mixed up some things,

      my graph-holding scroll pane is displayed within a JDialog (not JFrame) - could it be, that java doesn't clean up the dialog-related stuff on closing the dialog? Which way should I go, implementing a Component, that holds my graph and can be "destroyed" completely?

      @Martien
      could it be possible to post any more than this one line of code? I don't get, what is treeview in your app and where the setVisualization(null) comes from

      *totally confused*

       
    • MartienNL

      MartienNL - 2007-08-28

      Pff. how different are our names Martina and Martien.

      The easy answer, yes, Java will clean up, but only if you don't hold any reference to the memory. And the time it will clean-up is not known. The clean-up will be done by the garbagecollector and it is implementation dependend (Java VM) WHEN it will be executed. So you don't know when (nobody knows).
      The incredible line of code is about my implementation of the treeview. Basicly I mean that, whatever view you use, you should set its visualization to null. In my case it is the treeview, in yours it will be the NodeTreeLinkLayout.

      Perhaps some foolish: But you create the dialog and I presume you do a .setVisible(true) to it. This means that after the user closes the dialog, you return to the next line of code after the setVisible. Do you set the dialog variable to null? E.g.

            SomeDialog dialog = new SomeDialog();
            dialog.setVisible(true);
      ---> here it will return after the user closes the dialog
      ---> and it will keep the memory until:
            dialog = null;

      Martien

       
    • Martina

      Martina - 2007-08-28

      Thanks Martien (yeah, I realized that about our names too ;) )

      I will try that "dialog set to null" thing... I don't do that at the moment...

       
    • Martina

      Martina - 2007-08-29

      Well, that didn't seem to work, there must be something I have got wrong...

      I'll post my code here:

      First I have class, that creates a Jframe, afterwards it creates a dialog:

                        JDialog dia = new JDialog();
             
                    // create a testgraph
                Graph g = new Graph(true);
              
                g.addColumn("name", String.class);
                Node n1 = g.addNode(); 
                Node n2 = g.addNode();
                Node n3 = g.addNode();
              
                n1.setString("name","ROOT");
                n2.setString("name","is happy");
                n3.setString("name","is sad");
              
                g.addEdge(n2, n1);
                g.addEdge(n3, n1);       
             
                Display display  = new PrefuseConverter2(g, "name");
             
              dia.add(display);
              dia.pack();
              dia.setVisible(true);
             
              dia=null;
              ((PrefuseConverter2)display).clearall();

       
      • MartienNL

        MartienNL - 2007-08-29

               
                  Display display  = new PrefuseConverter2(g, "name");
               
                dia.add(display);
                dia.pack();
                dia.setVisible(true);
               
                dia=null;
                ((PrefuseConverter2)display).clearall();

        After these lines, you still have the reference display pointing to the PrefuseConverter. Try to set this one as well to null.

        I tried myself with my own implementation and I don't see that it holds the memory.
        However I've seen some note of a japanese guy about memory leaks (http://www.illigal.uiuc.edu/web/saru/category/programming/).
        So basicly I can't see the leak myself. But I'll try to investigate it further in my own application. If it is really the case, I will have a problem as well, because my implementation is one big TreeView with each time creating one additional treeview for a part of it, closing that one and when the user selects it, another treeview for another part. So I should see something of it. I'll take a look at my implementation.

        Regards,

        Martien

         
    • Martina

      Martina - 2007-08-29

      my other class, PrefuseConverter2 is mostly like the demo class TreeView with following constructor:

           public PrefuseConverter2(Graph t, String label) {

              super(new Visualization());

              m_label = label;
              m_vis.add(tree, t);

              m_nodeRenderer = new LabelRenderer(m_label);
              m_nodeRenderer.setRenderType(AbstractShapeRenderer.RENDER_TYPE_FILL);
              m_nodeRenderer.setHorizontalAlignment(Constants.LEFT);
              m_nodeRenderer.setRoundedCorner(8,8);
              m_edgeRenderer = new EdgeRenderer(Constants.EDGE_TYPE_CURVE);

              DefaultRendererFactory rf = new DefaultRendererFactory(m_nodeRenderer);
              rf.add(new InGroupPredicate(treeEdges), m_edgeRenderer);
              m_vis.setRendererFactory(rf);

              ItemAction nodeColor = new NodeColorAction(treeNodes);
              ItemAction textColor = new ColorAction(treeNodes,VisualItem.TEXTCOLOR, ColorLib.rgb(0,0,0));
              m_vis.putAction("textColor", textColor);

              ItemAction edgeColor = new ColorAction(treeEdges,VisualItem.STROKECOLOR, ColorLib.rgb(200,200,200));

              ActionList repaint = new ActionList();
              repaint.add(nodeColor);
              repaint.add(new RepaintAction());
              m_vis.putAction("repaint", repaint);
             
              // full paint
              ActionList fullPaint = new ActionList();
              fullPaint.add(nodeColor);
              m_vis.putAction("fullPaint", fullPaint);  

              // animate paint change
              ActionList animatePaint = new ActionList(400);
              animatePaint.add(new ColorAnimator(treeNodes));
              animatePaint.add(new RepaintAction());
              m_vis.putAction("animatePaint", animatePaint);

             
              // create the tree layout action
              NodeLinkTreeLayout treeLayout = new NodeLinkTreeLayout(tree, m_orientation, 50, 0, 8);
              treeLayout.setLayoutAnchor(new Point2D.Double(25,300));
              m_vis.putAction("treeLayout", treeLayout);

             CollapsedSubtreeLayout subLayout = new CollapsedSubtreeLayout(tree, m_orientation);
              m_vis.putAction("subLayout", subLayout);

                   // create the filtering and layout
              ActionList filter = new ActionList();
              filter.add(new FontAction(treeNodes, FontLib.getFont("Tahoma", 16)));
              filter.add(treeLayout);
              filter.add(subLayout);
              filter.add(textColor);
              filter.add(nodeColor);
              filter.add(edgeColor);

              m_vis.putAction("filter", filter);

             
              // initialize the display
              setSize(700,600);
              addControlListener(new ZoomToFitControl());
              addControlListener(new ZoomControl());
              addControlListener(new PanControl());

             
              setOrientation(m_orientation);
              m_vis.run("filter");
          }

      Other methods like set-/getOrientation etc are exactly like in the TreeViewDemo...

      When monitoring my little TestProg I still notice, that the prefuse stuff remains within memory, even after closing the dialog and setting to null. I don't know what to try any more...

      I tried things like

                     m_vis.cancel("filter")
                     m_vis.reset()

      or even       m_vis = null

      (last one results in a NullPointerException!)

      Please, any more suggestions what to do? Really desperate right now...

      Thanks,
      Martina

       
    • Martina

      Martina - 2007-08-29

      As I forgot :

      in the    PrefuseConverter.clearall()      from above I tried these things like resetting visualization etc...

       
    • Martina

      Martina - 2007-08-30

      Hi Martien

      thanks so much for kind of "sharing" the prob with me...
      By now I have tried a

      display = null;

      as well as a

      display.setVisualization(null);

      Both don't free the memory, but produce new problems. In the first case, I don't get anything of the graph displayed any more, in the second case, I receive a Null Pointer Exception...

      *sigh*

       
      • MartienNL

        MartienNL - 2007-08-30

        Pffff. Yes you are right. I see definitely a growing of memory. I tried now with 20 times creating the other graphs and yes memory is growing and ok it decreases a bit, but on the whole it is only growing.
        Because my test trees are not that big, I didn't notice it. But I do know the real ones using my app will be big, so we have the same problem.

        Anyone else having found a solution?

        Martien

         
    • Martina

      Martina - 2007-08-30

      OH OK, at least I am not the only one facing this problem... kind of doubted my code by now :)

      Well I really would appreciate any further hint... I'd really like to use the prefuse graphs, but the growing memory is a k.o. criterium for my app... I'm afraid, but times running for me (writing my master thesis) and if I don't find a solution until sunday or so, i will have to search another graph lib and rewrite everything *sigh*

      Please, anyone out there, who solved this or at least who can say "its not solvable" - then I'd switch immediately...

       
    • MartienNL

      MartienNL - 2007-08-30

      Martina,

      I tried the suggestions from Shunsuke Saruwatari (thanks to http://www.illigal.uiuc.edu/web/saru/2007/07/17/prefuse-memory-leak/ ). And the ones that paid off the most are:

      The class you extend from display, add the lines:
          public void cleanup() {
            m_offscreen = null;
            m_queue = null;
          }
      And call this method after you are finished with that display. This resolved for me 80% of the leaks. The point here is that a finalizer should do that for you (but that is not solved nicely in Java), but this is the easiest way for a quick test.

      I still have some tables in prefuse leaves and that have to be cleaned up, but have not figured out how to do that easy.

      Martien

       
    • Martina

      Martina - 2007-08-30

      WOW, thanks so far... I read the thread from this guy, but I have to admit, didn't know exactly what to do... I'll try that out at onece, sounds good :)

       
    • Martina

      Martina - 2007-08-30

      mhmmmm seems like I am toooo dump to do it...

      my code is:

                     JDialog dia = new JDialog();
                       
              Display display  = new PrefuseConverter2(g, "name");
             
              dia.add(display);
              dia.pack();
              dia.setVisible(true);
             
              dia=null;
             
              ((PrefuseConverter2)display).cleanup();   

      but now I am receivin a null pointer like this:

      Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
          at prefuse.Display.findItem(Display.java:1487)
          at prefuse.Display$InputEventCapturer.mouseMoved(Display.java:1533)
          at java.awt.Component.processMouseMotionEvent(Component.java:5599)
          at javax.swing.JComponent.processMouseMotionEvent(JComponent.java:3144)
          at java.awt.Component.processEvent(Component.java:5323)
          at java.awt.Container.processEvent(Container.java:2010)
          at java.awt.Component.dispatchEventImpl(Component.java:4021)
          at java.awt.Container.dispatchEventImpl(Container.java:2068)
          at java.awt.Component.dispatchEvent(Component.java:3869)
          at java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4256)
          at java.awt.LightweightDispatcher.processMouseEvent(Container.java:3949)
          at java.awt.LightweightDispatcher.dispatchEvent(Container.java:3866)
          at java.awt.Container.dispatchEventImpl(Container.java:2054)
          at java.awt.Window.dispatchEventImpl(Window.java:1774)
          at java.awt.Component.dispatchEvent(Component.java:3869)
          at java.awt.EventQueue.dispatchEvent(EventQueue.java:463)
          at java.awt.EventDispatchThread.pumpOneEventForHierarchy(EventDispatchThread.java:269)
          at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:190)
          at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:184)
          at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:176)
          at java.awt.EventDispatchThread.run(EventDispatchThread.java:110)

       
    • Martina

      Martina - 2007-08-30

      the cleanup is exactly what you posted above and I added it to my PrefuseConverter2 which is a subclass of  Display...

       
      • MartienNL

        MartienNL - 2007-08-30

        Ok,

        You have the lines:

               
                dia=null;
               
                ((PrefuseConverter2)display).cleanup();   

        I should change it like:

                ((PrefuseConverter2)display).cleanup();     // first clean it up
                        display = null;  // really give the display a go to gc
                        dia = null; // now all is free to go.

        If the error persist, I don't know, because it looks like it is still running the dialog. And while I write this.... Do you dispose the dialog? It looks like you don't do that. I mean closing the dialog with a button that has the dispose() call in it?

        Martien

         
    • Martina

      Martina - 2007-08-30

      hmmm, the error persists...

      as a last desperate try here is my whole test-class, which initializes my Dialog...

           public class TestPrefuseHeap implements ActionListener{

          public JFrame frame;
          public JPanel panel;
          public JButton button;
          private Display display;
          private JDialog dia;
         
          public TestPrefuseHeap(){
              frame = new JFrame("test");
              panel = new JPanel();
              button = new JButton("graph");
              button.addActionListener(this);
              panel.add(button);
              frame.getContentPane().add(panel);
              frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
              frame.pack();
              frame.setVisible(true);
          }
         
          public void createGraph(){
              dia = new JDialog();
              dia.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
              
                Graph g = new Graph(true);
              
                g.addColumn("name", String.class);
                Node n1 = g.addNode(); 
                Node n2 = g.addNode();
                Node n3 = g.addNode();
              
                n1.setString("name","ROOT");
                n2.setString("name","is happy");
                n3.setString("name","is sad");
              
                g.addEdge(n2, n1);
                g.addEdge(n3, n1);       
             
              display  = new PrefuseConverter2(g, "name");
             
              dia.add(display);
              dia.pack();
              dia.setVisible(true);       
          }
         
         
          public void del(){
              ((PrefuseConverter2)display).cleanup();   
              display = null;
              dia=null;       
             
          }
         
         
          public void actionPerformed(ActionEvent arg0) {
              if(arg0.getSource() == this.button){
                  this.createGraph();
              }
          }
         
         
          public static void main(String[] args) {
              TestPrefuseHeap t = new TestPrefuseHeap();
          }
           }

      Get the feeling, that I just oversee something really obvious or trivial, but I don't get it...

       
    • MartienNL

      MartienNL - 2007-08-30

      What also helped in this is to call to the graph (or tree) the methods:

      tree.clear();
      tree.dispose();

      In your case it is g.clear() and g.dispose() after the display=null;

      This did cut the number of hashmap entries by 2. But what I cannot solve is the number of listeners to the graph. Those cannot be removed, because the list is private in Graph and there is no method in graph to go through all listeners. Too bad. It will be a small change in the source of Graph. Just a new method removeAllListeners() with an iterator over the listeners to remove them.

      My problem is solved now for the good. My memory with 20 times opening and closing a dialog with testdata, which first hold memory on heap till 20M has now been lowered to 6M and without opening them it was 5.3M, so I loose 0.7M for a leak and that is fine with me. I guess most of it is from the listeners. So if in real life I have problems, I will change Graph myself.

      But as I can see you have another problem, possibly not to do with prefuse. Could you post the other file also complete, so I can try it?

      Regards,

      Martien

       
    • Martina

      Martina - 2007-08-30

      Yes of course...

      here is the complete one that creates the dialog (with imports etc)

      import java.awt.event.ActionEvent;
      import java.awt.event.ActionListener;

      import javax.swing.JButton;
      import javax.swing.JDialog;
      import javax.swing.JFrame;
      import javax.swing.JPanel;

      import prefuse.Display;
      import prefuse.data.Graph;
      import prefuse.data.Node;

      public class TestPrefuseHeap implements ActionListener{

          public JFrame frame;
          public JPanel panel;
          public JButton button;
          private Display display;
          private JDialog dia;
         
          public TestPrefuseHeap(){
              frame = new JFrame("test");
              panel = new JPanel();
              button = new JButton("graph");
              button.addActionListener(this);
              panel.add(button);
              frame.getContentPane().add(panel);
              frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
              frame.pack();
              frame.setVisible(true);
          }
         
          public void createGraph(){
              dia = new JDialog();
              dia.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
              
                Graph g = new Graph(true);
              
                g.addColumn("name", String.class);
                Node n1 = g.addNode(); 
                Node n2 = g.addNode();
                Node n3 = g.addNode();
              
                n1.setString("name","ROOT");
                n2.setString("name","is happy");
                n3.setString("name","is sad");
              
                g.addEdge(n2, n1);
                g.addEdge(n3, n1);       
             
              display  = new PrefuseConverter2(g, "name");
             
              dia.add(display);
              dia.pack();
              dia.setVisible(true);       
          }
         
         
          public void del(){
              ((PrefuseConverter2)display).cleanup();   
              display = null;
              dia=null;       
             
          }
         
         
          public void actionPerformed(ActionEvent arg0) {
              if(arg0.getSource() == this.button){
                  this.createGraph();
              }
          }
         
         
          public static void main(String[] args) {
              TestPrefuseHeap t = new TestPrefuseHeap();
          }
      }

      and here the complete prefuse converter:

      package testClasses;

      import java.awt.BorderLayout;

      import java.awt.Color;

      import java.awt.Dimension;

      import java.awt.Font;

      import java.awt.event.ActionEvent;

      import java.awt.event.MouseEvent;

      import java.awt.geom.Point2D;

      import javax.swing.AbstractAction;

      import javax.swing.BorderFactory;

      import javax.swing.Box;

      import javax.swing.BoxLayout;

      import javax.swing.JComponent;

      import javax.swing.JFrame;

      import javax.swing.JPanel;

      import javax.swing.KeyStroke;

      import javax.swing.SwingConstants;

      import prefuse.Constants;

      import prefuse.Display;

      import prefuse.Visualization;

      import prefuse.action.Action;

      import prefuse.action.ActionList;

      import prefuse.action.ItemAction;

      import prefuse.action.RepaintAction;

      import prefuse.action.animate.ColorAnimator;

      import prefuse.action.animate.LocationAnimator;

      import prefuse.action.animate.QualityControlAnimator;

      import prefuse.action.animate.VisibilityAnimator;

      import prefuse.action.assignment.ColorAction;

      import prefuse.action.assignment.FontAction;

      import prefuse.action.filter.FisheyeTreeFilter;

      import prefuse.action.layout.CollapsedSubtreeLayout;

      import prefuse.action.layout.graph.NodeLinkTreeLayout;

      import prefuse.activity.SlowInSlowOutPacer;

      import prefuse.controls.ControlAdapter;

      import prefuse.controls.FocusControl;

      import prefuse.controls.PanControl;

      import prefuse.controls.ZoomControl;

      import prefuse.controls.ZoomToFitControl;

      import prefuse.data.Graph;
      import prefuse.data.Tree;

      import prefuse.data.Tuple;

      import prefuse.data.event.TupleSetListener;

      import prefuse.data.io.TreeMLReader;

      import prefuse.data.search.PrefixSearchTupleSet;

      import prefuse.data.tuple.TupleSet;

      import prefuse.render.DefaultRendererFactory;

      import prefuse.render.EdgeRenderer;

      import prefuse.render.AbstractShapeRenderer;

      import prefuse.render.LabelRenderer;

      import prefuse.util.ColorLib;

      import prefuse.util.FontLib;

      import prefuse.util.ui.JFastLabel;

      import prefuse.util.ui.JSearchPanel;

      import prefuse.visual.VisualItem;

      import prefuse.visual.expression.InGroupPredicate;

      import prefuse.visual.sort.TreeDepthItemSorter;

      /**

      * Demonstration of a node-link tree viewer

      *

      * @version 1.0

      * @author <a href="http://jheer.org">jeffrey heer</a>

      */

      public class PrefuseConverter2 extends Display {

          public static final String TREE_CHI = "/chi-ontology.xml.gz";

         

          private static final String tree = "tree";

          private static final String treeNodes = "tree.nodes";

          private static final String treeEdges = "tree.edges";

         

          private LabelRenderer m_nodeRenderer;

          private EdgeRenderer m_edgeRenderer;

         

          private String m_label = "name";

          private int m_orientation = Constants.ORIENT_LEFT_RIGHT;

         

          public PrefuseConverter2(Graph t, String label) {

              super(new Visualization());

              m_label = label;
              m_vis.add(tree, t);

              m_nodeRenderer = new LabelRenderer(m_label);
              m_nodeRenderer.setRenderType(AbstractShapeRenderer.RENDER_TYPE_FILL);
              m_nodeRenderer.setHorizontalAlignment(Constants.LEFT);
              m_nodeRenderer.setRoundedCorner(8,8);
              m_edgeRenderer = new EdgeRenderer(Constants.EDGE_TYPE_CURVE);

              DefaultRendererFactory rf = new DefaultRendererFactory(m_nodeRenderer);
              rf.add(new InGroupPredicate(treeEdges), m_edgeRenderer);
              m_vis.setRendererFactory(rf);

              ItemAction nodeColor = new NodeColorAction(treeNodes);
              ItemAction textColor = new ColorAction(treeNodes,VisualItem.TEXTCOLOR, ColorLib.rgb(0,0,0));
              m_vis.putAction("textColor", textColor);

              ItemAction edgeColor = new ColorAction(treeEdges,VisualItem.STROKECOLOR, ColorLib.rgb(200,200,200));

              ActionList repaint = new ActionList();
              repaint.add(nodeColor);
              repaint.add(new RepaintAction());
              m_vis.putAction("repaint", repaint);
             
              // full paint
              ActionList fullPaint = new ActionList();
              fullPaint.add(nodeColor);
              m_vis.putAction("fullPaint", fullPaint);  

              // animate paint change
              ActionList animatePaint = new ActionList(400);
              animatePaint.add(new ColorAnimator(treeNodes));
              animatePaint.add(new RepaintAction());
              m_vis.putAction("animatePaint", animatePaint);

             
              // create the tree layout action
              NodeLinkTreeLayout treeLayout = new NodeLinkTreeLayout(tree, m_orientation, 50, 0, 8);
              treeLayout.setLayoutAnchor(new Point2D.Double(25,300));
              m_vis.putAction("treeLayout", treeLayout);

             CollapsedSubtreeLayout subLayout = new CollapsedSubtreeLayout(tree, m_orientation);
              m_vis.putAction("subLayout", subLayout);

                   // create the filtering and layout
              ActionList filter = new ActionList();
              filter.add(new FontAction(treeNodes, FontLib.getFont("Tahoma", 16)));
              filter.add(treeLayout);
              filter.add(subLayout);
              filter.add(textColor);
              filter.add(nodeColor);
              filter.add(edgeColor);

              m_vis.putAction("filter", filter);

             
              // initialize the display
              setSize(700,600);
              addControlListener(new ZoomToFitControl());
              addControlListener(new ZoomControl());
              addControlListener(new PanControl());

             
              setOrientation(m_orientation);
              m_vis.run("filter");
          }
             

              // ------------------------------------------------------------------------

         

          public void setOrientation(int orientation) {

              NodeLinkTreeLayout rtl

                  = (NodeLinkTreeLayout)m_vis.getAction("treeLayout");

              CollapsedSubtreeLayout stl

                  = (CollapsedSubtreeLayout)m_vis.getAction("subLayout");

              switch ( orientation ) {

              case Constants.ORIENT_LEFT_RIGHT:

                  m_nodeRenderer.setHorizontalAlignment(Constants.LEFT);

                  m_edgeRenderer.setHorizontalAlignment1(Constants.RIGHT);

                  m_edgeRenderer.setHorizontalAlignment2(Constants.LEFT);

                  m_edgeRenderer.setVerticalAlignment1(Constants.CENTER);

                  m_edgeRenderer.setVerticalAlignment2(Constants.CENTER);

                  break;

              case Constants.ORIENT_RIGHT_LEFT:

                  m_nodeRenderer.setHorizontalAlignment(Constants.RIGHT);

                  m_edgeRenderer.setHorizontalAlignment1(Constants.LEFT);

                  m_edgeRenderer.setHorizontalAlignment2(Constants.RIGHT);

                  m_edgeRenderer.setVerticalAlignment1(Constants.CENTER);

                  m_edgeRenderer.setVerticalAlignment2(Constants.CENTER);

                  break;

              case Constants.ORIENT_TOP_BOTTOM:

                  m_nodeRenderer.setHorizontalAlignment(Constants.CENTER);

                  m_edgeRenderer.setHorizontalAlignment1(Constants.CENTER);

                  m_edgeRenderer.setHorizontalAlignment2(Constants.CENTER);

                  m_edgeRenderer.setVerticalAlignment1(Constants.BOTTOM);

                  m_edgeRenderer.setVerticalAlignment2(Constants.TOP);

                  break;

              case Constants.ORIENT_BOTTOM_TOP:

                  m_nodeRenderer.setHorizontalAlignment(Constants.CENTER);

                  m_edgeRenderer.setHorizontalAlignment1(Constants.CENTER);

                  m_edgeRenderer.setHorizontalAlignment2(Constants.CENTER);

                  m_edgeRenderer.setVerticalAlignment1(Constants.TOP);

                  m_edgeRenderer.setVerticalAlignment2(Constants.BOTTOM);

                  break;

              default:

                  throw new IllegalArgumentException(

                      "Unrecognized orientation value: "+orientation);

              }

              m_orientation = orientation;

              rtl.setOrientation(orientation);

              stl.setOrientation(orientation);

          }

         

          public int getOrientation() {

              return m_orientation;

          }

         

          // ------------------------------------------------------------------------

         

          public static void main(String argv[]) {

              String infile = TREE_CHI;

              String label = "name";

              if ( argv.length > 1 ) {

                  infile = argv[0];

                  label = argv[1];

              }

              JComponent treeview = demo(infile, label);

             

              JFrame frame = new JFrame("p r e f u s e  |  t r e e v i e w");

              frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

              frame.setContentPane(treeview);

              frame.pack();

              frame.setVisible(true);

          }

         

          public static JComponent demo() {

              return demo(TREE_CHI, "name");

          }

         

          public static JComponent demo(String datafile, final String label) {

              Color BACKGROUND = Color.WHITE;

              Color FOREGROUND = Color.BLACK;

             

              Tree t = null;

              try {

                  t = (Tree)new TreeMLReader().readGraph(datafile);

              } catch ( Exception e ) {

                  e.printStackTrace();

                  System.exit(1);

              }

             

              // create a new treemap

              final PrefuseConverter2 tview = new PrefuseConverter2(t, label);

              tview.setBackground(BACKGROUND);

              tview.setForeground(FOREGROUND);

             

              // create a search panel for the tree map

              JSearchPanel search = new JSearchPanel(tview.getVisualization(),

                  treeNodes, Visualization.SEARCH_ITEMS, label, true, true);

              search.setShowResultCount(true);

              search.setBorder(BorderFactory.createEmptyBorder(5,5,4,0));

              search.setFont(FontLib.getFont("Tahoma", Font.PLAIN, 11));

              search.setBackground(BACKGROUND);

              search.setForeground(FOREGROUND);

             

              final JFastLabel title = new JFastLabel("                 ");

              title.setPreferredSize(new Dimension(350, 20));

              title.setVerticalAlignment(SwingConstants.BOTTOM);

              title.setBorder(BorderFactory.createEmptyBorder(3,0,0,0));

              title.setFont(FontLib.getFont("Tahoma", Font.PLAIN, 16));

              title.setBackground(BACKGROUND);

              title.setForeground(FOREGROUND);

             

              tview.addControlListener(new ControlAdapter() {

                  public void itemEntered(VisualItem item, MouseEvent e) {

                      if ( item.canGetString(label) )

                          title.setText(item.getString(label));

                  }

                  public void itemExited(VisualItem item, MouseEvent e) {

                      title.setText(null);

                  }

              });

             

              Box box = new Box(BoxLayout.X_AXIS);

              box.add(Box.createHorizontalStrut(10));

              box.add(title);

              box.add(Box.createHorizontalGlue());

              box.add(search);

              box.add(Box.createHorizontalStrut(3));

              box.setBackground(BACKGROUND);

             

              JPanel panel = new JPanel(new BorderLayout());

              panel.setBackground(BACKGROUND);

              panel.setForeground(FOREGROUND);

              panel.add(tview, BorderLayout.CENTER);

              panel.add(box, BorderLayout.SOUTH);

              return panel;

          }

         

          // ------------------------------------------------------------------------

        

          public class OrientAction extends AbstractAction {

              private int orientation;

             

              public OrientAction(int orientation) {

                  this.orientation = orientation;

              }

              public void actionPerformed(ActionEvent evt) {

                  setOrientation(orientation);

                  getVisualization().cancel("orient");

                  getVisualization().run("treeLayout");

                  getVisualization().run("orient");

              }

          }

         

          public class AutoPanAction extends Action {

              private Point2D m_start = new Point2D.Double();

              private Point2D m_end   = new Point2D.Double();

              private Point2D m_cur   = new Point2D.Double();

              private int     m_bias  = 150;

             

              public void run(double frac) {

                  TupleSet ts = m_vis.getFocusGroup(Visualization.FOCUS_ITEMS);

                  if ( ts.getTupleCount() == 0 )

                      return;

                 

                  if ( frac == 0.0 ) {

                      int xbias=0, ybias=0;

                      switch ( m_orientation ) {

                      case Constants.ORIENT_LEFT_RIGHT:

                          xbias = m_bias;

                          break;

                      case Constants.ORIENT_RIGHT_LEFT:

                          xbias = -m_bias;

                          break;

                      case Constants.ORIENT_TOP_BOTTOM:

                          ybias = m_bias;

                          break;

                      case Constants.ORIENT_BOTTOM_TOP:

                          ybias = -m_bias;

                          break;

                      }

                      VisualItem vi = (VisualItem)ts.tuples().next();

                      m_cur.setLocation(getWidth()/2, getHeight()/2);

                      getAbsoluteCoordinate(m_cur, m_start);

                      m_end.setLocation(vi.getX()+xbias, vi.getY()+ybias);

                  } else {

                      m_cur.setLocation(m_start.getX() + frac*(m_end.getX()-m_start.getX()),

                                        m_start.getY() + frac*(m_end.getY()-m_start.getY()));

                      panToAbs(m_cur);

                  }

              }

          }

         

          public static class NodeColorAction extends ColorAction {

             

              public NodeColorAction(String group) {

                  super(group, VisualItem.FILLCOLOR);

              }

             

              public int getColor(VisualItem item) {

                  if ( m_vis.isInGroup(item, Visualization.SEARCH_ITEMS) )

                      return ColorLib.rgb(255,190,190);

                  else if ( m_vis.isInGroup(item, Visualization.FOCUS_ITEMS) )

                      return ColorLib.rgb(198,229,229);

                  else if ( item.getDOI() > -1 )

                      return ColorLib.rgb(164,193,193);

                  else

                      return ColorLib.rgba(255,255,255,0);

              }

             

          } // end of inner class TreeMapColorAction

         
          public void cleanup() {
              m_offscreen = null;
              m_queue = null;
              }
         

          public void clearall(){
              m_vis.cancel("filter");
              m_vis.reset();
             
             
          }

      } // end of class TreeMap

       

      Thank you SO much in advance!!!

       
      • MartienNL

        MartienNL - 2007-08-30

        Hope you're happy now :-))

        package testmemoryleak;

        import java.awt.event.ActionEvent;
        import java.awt.event.ActionListener;
        import java.awt.event.WindowAdapter;
        import java.awt.event.WindowEvent;

        import javax.swing.JButton;
        import javax.swing.JDialog;
        import javax.swing.JFrame;
        import javax.swing.JPanel;

        import prefuse.Display;
        import prefuse.data.Graph;
        import prefuse.data.Node;
        import testClasses.PrefuseConverter2;

        public class TestPrefuseHeap implements ActionListener{

            public JFrame frame;
            public JPanel panel;
            public JButton button;
            private Display display;
            private JDialog dia;
                //--------->
            private Graph g; //added to allow del to access it
           
            public TestPrefuseHeap(){
                frame = new JFrame("test");
                panel = new JPanel();
                button = new JButton("graph");
                button.addActionListener(this);
                panel.add(button);
                frame.getContentPane().add(panel);
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.pack();
                frame.setVisible(true);
            }
           
            public void createGraph(){
                dia = new JDialog();
                        //----------> Invoke del() on close
        //        dia.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
                        dia.addWindowListener(new WindowAdapter() {
                            public void windowClosing(WindowEvent we) {
                                del();
                            }
                        });        
                          //-----> Use the private graph
                  g = new Graph(true);
                
                  g.addColumn("name", String.class);
                  Node n1 = g.addNode(); 
                  Node n2 = g.addNode();
                  Node n3 = g.addNode();
                
                  n1.setString("name","ROOT");
                  n2.setString("name","is happy");
                  n3.setString("name","is sad");
                
                  g.addEdge(n2, n1);
                  g.addEdge(n3, n1);       
               
                display  = new PrefuseConverter2(g, "name");
               
                dia.add(display);
                dia.pack();
                dia.setVisible(true);       
            }
           
           
            public void del(){
                ((PrefuseConverter2)display).cleanup();   
                display = null;
                dia=null;   
                        g.clear();
                        g.dispose();
               
            }
           
           
            public void actionPerformed(ActionEvent arg0) {
                if(arg0.getSource() == this.button){
                    this.createGraph();
                }
            }
           
           
            public static void main(String[] args) {
                TestPrefuseHeap t = new TestPrefuseHeap();
            }
        }

        The real difference is that you didnot dispose of the dialog. So it was still kept in memory and indeed it was growing fast.
        I added also the clear and dispose of the graph to it. Now I see about no changes in usage. If the garbagecollector is run, you're about the same size. So I think you're problem is solved now.
        A lot of success with you're master!!!

        Martien

         
1 2 > >> (Page 1 of 2)

Log in to post a comment.

Auth0 Logo