Expired UI instances not garbage collected

In our Vaadin / Spring application I have noticed that UI instances are not GC’ed when “they expire”. According to Vaadin documentation:

UI instances are cleaned up if no communication is received from them after some time. If no other server requests are made, the client-side sends keep-alive heartbeat requests. A UI is kept alive for as long as requests or heartbeats are received from it. It expires if three consecutive heartbeats are missed.

A session is kept alive by server requests caused by user interaction with the application as well as the heartbeat monitoring of the UIs. Once all UIs have expired, the session still remains. It is cleaned up from the server when the session timeout configured in the web application expires.

When I open 3 browser tabs (same browser/machine) and hit the application URL, one UI instances is created per tab (single VaadinSession instance). Using Wireshark, I can see the heartbeats being sent for each tab every 15 seconds (different ‘v-uiId’). When I close two of the tabs (without logging out), I observe that the heartbeats for those tabs are discontinued as expected. Accoring to the Vaadin documentation above, I would expect Vaadin to make the expired UI instances available for garbage collection. However, that seems not to be the case. In fact, UI instances are not GC’ed until the session expires. This happens 2 minutes after the LAST browser tab is closed (session timeout + 3 consecutive heartbeats missed).

I am aware of the ‘closeIdleSessions’ property, but this property closes the session (and all accociated UIs) even if heartbeats are sent as long as there is no user interaction. This will not fly in our case.

Have anybody observed similar behaviour / problem?

Our application is using ‘@SpringView()’ for automatic view registration (SpringNavigator). In addition, we are running with a one minute session timeout and a 15 second heartbeat interval (see configuration below).

// Our UI class has the following annotation @Theme("admin") @PreserveOnRefresh @SpringUI() @Widgetset("vaadinWidgetSet") @Push(PushMode.AUTOMATIC) public class Main extends UI implements IMain { ... } // A typical view would be something like: @UIScope @SpringView(name = "ViewId") public class SomeView extends VerticalLayout { ... } The following configuration is set in application.properties:

  • server.session.timeout=1
  • vaadin.servlet.heartbeatInterval=15

Environment

  • Spring Boot (1.5.3)
  • Vaadin Spring Boot (1.2.0)
  • Vaadin (7.7.8)
  • JDK 1.8.0_131

Finally figured it out!

After doing some memory profiling, I found an instance of the Vaadin Embedded class in the GC root path for my expired (but not GC’ed) UI instance. Playing around with some options, I figured the problem to be the combined usage of Embedded and ClassResource. As indicated below, using Image/ClassResource or Embedded/ThemeResource both work fine (no memory leak).

Also verified this using the Full Stack Starter resently provided by Vaadin (https://vaadin.com/full-stack-starter). Without any modifications, the starter works as expected. However, adding the code below re-creates the UI instance leak when closing the browser tabs as explained in my original post.

Note!
The same bug is present in Vaadin 7.5.0 with Spring 4.1.5.RELEASE (no Spring Boot).

PS
You will need to copy the ‘icon-192.png’ image to ‘src/main/resources’ for the image to show (not needed for the leak though).

// Modified methid is DashboardView.init()
.
.
.
Embedded image = new Embedded(null, new ClassResource("/icon-192.png"));  // Leaks UI instance
//Image image = new Image(null, new ClassResource("/icon-192.png"));      // Works (no leak)
//Embedded image = new Embedded(null, new ThemeResource("icon-192.png")); // Works (no leak)
//Image image = new Image(null, new ThemeResource("icon-192.png"));       // Works (no leak)
row = board.addRow(new BoardBox(deliveriesThisMonthGraph), new BoardBox(image), new BoardBox(deliveriesThisYearGraph)); // New BoardBox added

I just noticed that after refreshing the page, previous UI instances remain alive. This is using Spring Boot with @SpringView as well. However, I’m not using Embedded.

Herman Bovens:
I just noticed that after refreshing the page, previous UI instances remain alive. This is using Spring Boot with @SpringView as well. However, I’m not using Embedded.

Hi Herman and Per-Ivar, I’m now encountering the same problem.

Were either of you able to solve this?

Matthew Scott:

Herman Bovens:
I just noticed that after refreshing the page, previous UI instances remain alive. This is using Spring Boot with @SpringView as well. However, I’m not using Embedded.

Hi Herman and Per-Ivar, I’m now encountering the same problem.

Were either of you able to solve this?

Hi Matthew

As I understand it, Herman had a slightly different issue than I originally posted. Hence, if you have the same issue as Herman you might look into using the @PreserveOnRefresh annotation. This should prevent new UI instances from being created when you refresh your browser.

Per-Ivar Bakke:

Matthew Scott:

Herman Bovens:
I just noticed that after refreshing the page, previous UI instances remain alive. This is using Spring Boot with @SpringView as well. However, I’m not using Embedded.

Hi Herman and Per-Ivar, I’m now encountering the same problem.

Were either of you able to solve this?

Hi Matthew

As I understand it, Herman had a slightly different issue than I originally posted. Hence, if you have the same issue as Herman you might look into using the @PreserveOnRefresh annotation. This should prevent new UI instances from being created when you refresh your browser.

Hi Per-Ivar, thanks for the response. I think the issue I’m having is more closely related to yours than Herman’s.

I’ve done a scan for Embedded resources and ClassResources, and have corrected any suspicious code, but all of the UI’s and associated components are still being stubborn.

No GC seems to be working on them.

Is there anything else you did to solve the problem, or was there a Spring-Boot issue that you needed to solve?

Hi Matthew

As described in my post above (July 3rd 2017), the leaking UI instance seemed to be related to the use of Embedded / ClassResource. This looks like a Vaadin bug, since the 3 other alternatives all seemed to work just fine (see code snippet in mentioned post). Also, note that the issue was re-produced using the Full Stack Starter from Vaddin, further indicating this to be a bug in Vaadin.

Now, if you have the same issue … and you are not using Embedded / ClassResource, I think you would need to profile your code to determine what is preventing your UI instance from being garbage collected (who has reference to your instance). I used JProfiler for this.