View unanswered posts | View active topics It is currently Mon May 01, 2017 1:38 am



Reply to topic  [ 10 posts ] 
 Memory leak with JavaFX and MigPane 
Author Message

Joined: Mon Dec 14, 2009 4:40 pm
Posts: 5
Post Memory leak with JavaFX and MigPane
Hello,

I've run into problems with JavaFX and MigPane when adding and deleting many items to a ListView. To reproduce the problem I wrote a small application. When using javafx.scene.layout.FlowPane as layout container for the list items the memory consumtion stops unchanged at about 65MB but when using org.tbee.javafx.scene.layout.MigPane it raises until an java.lang.OutOfMemoryError occurs at about 400MB.
System: Windows 7 64 Bit
VM: JRE 7, 32 Bit
JavaFX: 2.2.3
MigLayout: 4.2
Quote:
loop 15718
loop 15719
loop 15720
Exception in runnable
java.lang.OutOfMemoryError: Java heap space
at sun.util.resources.TimeZoneNames.getContents(Unknown Source)
at sun.util.resources.OpenListResourceBundle.loadLookup(Unknown Source)
at sun.util.resources.OpenListResourceBundle.loadLookupTablesIfNecessary(Unknown Source)
loop 15721 at sun.util.resources.OpenListResourceBundle.handleGetObject(Unknown Source)
at sun.util.resources.TimeZoneNamesBundle.handleGetObject(Unknown Source)
at java.util.ResourceBundle.getObject(Unknown Source)
at java.util.ResourceBundle.getObject(Unknown Source)

at java.util.ResourceBundle.getStringArray(Unknown Source)
at sun.util.TimeZoneNameUtility.retrieveDisplayNames(Unknown Source)
at sun.util.TimeZoneNameUtility.retrieveDisplayNames(Unknown Source)
at java.util.TimeZone.getDisplayNames(Unknown Source)
at java.util.TimeZone.getDisplayName(Unknown Source)
at java.util.Date.toString(Unknown Source)loop 15722

at java.lang.String.valueOf(Unknown Source)
at java.lang.StringBuilder.append(Unknown Source)
at listviewtest.Main$ListElement.<init>(Main.java:34)
loop 15723
at listviewtest.Main$1$1$1.run(Main.java:84)
at com.sun.javafx.application.PlatformImpl$4.run(PlatformImpl.java:173)
at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
at com.sun.glass.ui.win.WinApplication.access$100(WinApplication.java:29)
loop 15724
at com.sun.glass.ui.win.WinApplication$3$1.run(WinApplication.java:73)
at java.lang.Thread.run(Unknown Source)
loop 15725
loop 15726
loop 15727
loop 15728
loop 15729
Exception in runnable
java.lang.OutOfMemoryError: Java heap space
at sun.util.resources.TimeZoneNames.getContents(Unknown Source)
at sun.util.resources.OpenListResourceBundle.loadLookup(Unknown Source)
at sun.util.resources.OpenListResourceBundle.loadLookupTablesIfNecessary(Unknown Source)
loop 15730
at sun.util.resources.OpenListResourceBundle.handleGetObject(Unknown Source)
at sun.util.resources.TimeZoneNamesBundle.handleGetObject(Unknown Source)
at java.util.ResourceBundle.getObject(Unknown Source)
at java.util.ResourceBundle.getObject(Unknown Source)
at java.util.ResourceBundle.getStringArray(Unknown Source)
loop 15731
at sun.util.TimeZoneNameUtility.retrieveDisplayNames(Unknown Source)
at sun.util.TimeZoneNameUtility.retrieveDisplayNames(Unknown Source)
at java.util.TimeZone.getDisplayNames(Unknown Source)
at java.util.TimeZone.getDisplayName(Unknown Source)
at java.util.Date.toString(Unknown Source)
at java.lang.String.valueOf(Unknown Source)


Here's the code of the leaking application. It just starts a thread and deletes and adds elements to the underlying list of the ListView. In our productive application the exception occurs much faster because the list elements are more complex and the application generally consumes more memory.
As I've told before the exception doesn't occur if I derive the ListElement class from javafx.scene.layout.FlowPane

Code:
package listviewtest;

import java.util.Date;

import javafx.application.Application;
import javafx.application.Platform;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.ButtonBuilder;
import javafx.scene.control.Label;
import javafx.scene.control.LabelBuilder;
import javafx.scene.control.ListView;
import javafx.scene.layout.BorderPaneBuilder;
import javafx.scene.layout.HBoxBuilder;
import javafx.scene.layout.VBoxBuilder;
import javafx.stage.Stage;

import org.tbee.javafx.scene.layout.fxml.MigPane;

public class Main extends Application {

   public static class ListElement extends MigPane {

      public ListElement(int i, Date date) {
         LabelBuilder<?> lb = LabelBuilder.create();
         Label title = lb.text("Element " + i).build();
         Label info = lb.text("element created at: " + date).build();

         add(
                 VBoxBuilder.create().children(title, info).build());

         ButtonBuilder<?> bb = ButtonBuilder.create().mnemonicParsing(false);
         Button b1 = bb.text("button-1").build();
         Button b2 = bb.text("button-2").build();
         Button b3 = bb.text("button-3").build();

         add(HBoxBuilder.create().children(b1, b2, b3).build());

      }

   }

   private ObservableList<ListElement> items;

   public Main() {
      super();
      this.items = FXCollections.observableArrayList();
   }

   private Parent createRoot() {

      final ListView<Main.ListElement> listView = new ListView<Main.ListElement>();
      listView.setItems(this.items);

      final Button testButton = ButtonBuilder.create().text("Start test")
              .maxWidth(Double.MAX_VALUE).build();

      testButton.setOnAction(new EventHandler<ActionEvent>() {

         @Override
         public void handle(final ActionEvent ev) {

            final Thread t = new Thread() {

               @Override
               public void run() {
                  for (int loop = 0; loop < Integer.MAX_VALUE; loop++) {

                     System.out.println("loop " + loop);

                     Platform.runLater(new Runnable() {

                        @Override
                        public void run() {
                           items.clear();
                           for (int i = 0; i < 10; i++) {
                              items.add(new ListElement(i, new Date()));
                           }
                        }
                     });
                     try {
                        Thread.sleep(10);
                     } catch (final InterruptedException e) {
                        // do nothing
                     }
                  }
               }

            };
            t.setDaemon(true);
            t.start();
         }
      });

      return BorderPaneBuilder.create().center(listView).bottom(testButton)
              .build();
   }

   @Override
   public void start(Stage stage) throws Exception {
      Parent root = createRoot();
      Scene scene = new Scene(root);
      stage.setScene(scene);
      stage.setWidth(800);
      stage.setHeight(600);
      stage.show();
   }

   public static void main(String[] args) {
      launch(args);
   }

}



Tue Oct 23, 2012 12:40 pm
Profile
Site Admin

Joined: Mon Dec 06, 2004 4:24 pm
Posts: 2485
Location: Sweden
Post Re: Memory leak with JavaFX and MigPane
Ok. Thanks for the test case.

I will notify the creator of the JavaFX version and see what he has to say.

Thanks,
Mikael


Wed Oct 24, 2012 12:09 am
Profile WWW

Joined: Thu Oct 25, 2007 3:18 pm
Posts: 96
Post Re: Memory leak with JavaFX and MigPane
I will look into this ASAP, but that probably will mean somewhere in the second half of next week. Got some high priority things right now.


Wed Oct 24, 2012 9:26 am
Profile

Joined: Thu Oct 25, 2007 3:18 pm
Posts: 96
Post Re: Memory leak with JavaFX and MigPane
Ok, I'm sure it are not MigPane's collections that fill up. So I'm going to make a memory dump and see what is eating the memory.


Tue Nov 06, 2012 1:03 pm
Profile

Joined: Thu Oct 25, 2007 3:18 pm
Posts: 96
Post Re: Memory leak with JavaFX and MigPane
Hmmm, everything points to that the nodes are being held by the scene, not Mig.


Tue Nov 06, 2012 1:39 pm
Profile

Joined: Thu Oct 25, 2007 3:18 pm
Posts: 96
Post Re: Memory leak with JavaFX and MigPane
Ok. This is what I see in the memory analysis of a single Button (there are 39000+ of them in memory).

Code:
Class Name                                                                       | Shallow Heap | Retained Heap

javafx.scene.control.Button at 0x319ba2f8                                         |          408 |         1,672
- [60490] javafx.scene.Node[98113] at 0x29cc8810                                 |      392,464 |       392,464
   - dirtyNodes javafx.scene.Scene at 0x27f65d00                                 |          376 |       396,728
      |- this$0 javafx.scene.Scene$ScenePeerListener at 0x28003d60                |           16 |            16
      |  - sceneListener com.sun.javafx.tk.quantum.ViewScene at 0x27ffb710       |           64 |           168
      |     |- scene com.sun.javafx.tk.quantum.PrismPen at 0x27ffc7f0             |           48 |         2,344
      |     |  - pen com.sun.glass.ui.win.WinView at 0x27ff4e98 Native Stack     |           72 |           480
      |     |- scene com.sun.javafx.tk.quantum.GlassViewEventHandler at 0x27ffc820|           48 |           408
      |     |- scene com.sun.javafx.tk.quantum.WindowStage at 0x27f694e8          |           88 |           184
      |     - Total: 3 entries                                                  |              |             
      |- this$0 javafx.scene.Scene$ScenePulseListener at 0x27f6a300               |           16 |            16
      |- oldScene, value javafx.scene.Node$4 at 0x31121ca8                        |           48 |            48
      - Total: 3 entries                                                        |              |             


There is no MigPane class involved in the path to the garbage collector. It seems it is primarily being held by the dirtyNodes collection in the scene. But that would contradict the fact that is works without problems in when using a standard layout.


Tue Nov 06, 2012 9:51 pm
Profile

Joined: Thu Oct 25, 2007 3:18 pm
Posts: 96
Post Re: Memory leak with JavaFX and MigPane
I can reproduce that with FlowPane it does not run out of memory, but I cannot figure out where it is hung up when Using MigPane. MigPane only uses weak collections, except one (which I temporarily recoded to weak as well). The memory dump does not indicate MigPane holding a reference... I'm stuck.


Tue Nov 06, 2012 11:59 pm
Profile
Site Admin

Joined: Mon Dec 06, 2004 4:24 pm
Posts: 2485
Location: Sweden
Post Re: Memory leak with JavaFX and MigPane
Can it be a tight/infinite loop that re-layouts the components so that the dirtyNodes doesn't have time or get the chance to clear it?


Wed Nov 07, 2012 12:57 am
Profile WWW

Joined: Thu Oct 25, 2007 3:18 pm
Posts: 96
Post Re: Memory leak with JavaFX and MigPane
Then the same behavior should be occuring with FlowPane as well. Maybe a good night's sleep, some more time to look more closely, a different test case, ...


Wed Nov 07, 2012 1:40 am
Profile

Joined: Thu Oct 25, 2007 3:18 pm
Posts: 96
Post Re: Memory leak with JavaFX and MigPane
Ok. I still haven't found the cause, but did find a work-around. It's the instance ObservableList that is part of the problem. By replacing that with a new list on each iteration:

Code:
                           ObservableList<ListElement> items = FXCollections.observableArrayList();
                           for (int i = 0; i < 10; i++)
                           {
                              items.add(new ListElement(i, new Date()));
                           }
                           listView.setItems(items);


There is no out of memory exception. As said before: MigPane is not holding any references, no Mig* class is present in the whole path to GC, so the problem really has to be in JavaFX. It will be a challenge to figure out how this is caused.


Sun Nov 18, 2012 11:27 pm
Profile
Display posts from previous:  Sort by  
Reply to topic   [ 10 posts ] 

You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
cron
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group.
Designed by STSoftware for PTF.