question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Bootstrap page payload remains in ThreadLocal cache managed by JSoup

See original GitHub issue

Hello! I got a memory leak. I will describe it below as detailed as possible, and also attach a demo project to reproduce it on your machine.

Vaadin 14.0.4, Spring Boot 2.1.7, Java 11.0.4, Tomcat/Jetty/Undertow, macOS High Sierra + Safari.

Let’s take my-starter-project as a base.

application.properties:

vaadin.heartbeatInterval=5
server.servlet.session.timeout=60

MainView.java:

    private static String generateRandomString(java.util.Random rnd, int length){
        // Return some string of size `length`
		...
    }
@Route
@UIScope
@Push(transport = Transport.LONG_POLLING)
public class MainView extends VerticalLayout {
...
public MainView(@Autowired MessageBean bean) {
	Button button = new Button("Click me",
		e -> {
			Random rnd = new Random();
			for (int i = 0; i < 50; i++) {
				Div div = new Div();
				div.setText(generateRandomString(rnd, 1024 * 10));
				this.add(div);
			}
			Notification.show(bean.getMessage());
		});
	add(button);
}

The above code outputs to browser window 50 lines of 10Kb each, no issues. Now, let’s replace the constructor’s code.

public MainView(@Autowired MessageBean bean) {
	Random rnd = new Random();
	for (int i = 0; i < 50; i++) {
		Div div = new Div();
		div.setText(generateRandomString(rnd, 1024 * 10));
		this.add(div);
	}
}

The above code has an issue: a memory leak – several objects org.apache.tomcat.utils.threads.TaskThread are never destroyed (even after MainView objects count and SpringVaadinSession objects count become 0 due to session expiration). It is not related to servlet container, I tried all three available in Spring Boot: Tomcat, Jetty and Undertow. I attached a screenshot. It contains a string with Push data of AtmospherePushConnection (start with <!doctype html>...).

Problem

In constructor I pass a lot of data to user’s browser window (a large log file, instead of random string data as in this sample), so this memory leak steals a lot of memory at each page refresh and finally leads to OutOfMemory heap error.

my-starter-project.zip

Issue Analytics

  • State:closed
  • Created 4 years ago
  • Comments:5 (2 by maintainers)

github_iconTop GitHub Comments

1reaction
Legiothcommented, Sep 18, 2019

Based on my investigation, this isn’t a regular memory leak per se. Instead, this is a per-thread cache managed by JSoup that may under specific end up with quite much content. What it means is that memory use doesn’t grow without bounds, but instead only based on the number of request-serving threads used by the application server.

JSoup caches instances of StringBuilder to reduce the number of instances that would have to be garbage collected. The cache works so that there is one instance per Java thread, managed using a ThreadLocal. This is handled in the method org.jsoup.helper.StringUtil.stringBuilder().

Vaadin uses JSoup to build the bootstrap html page contents. Since this is the last use of JSoup in a typical Vaadin request, the full bootstrap page will remain in a cached string builder until the next time some JSoup functionality that uses a string builder is run on the same thread.

The caching was reimplemented in https://github.com/jhy/jsoup/issues/1059 because of issues similar to this and the fix was included in JSoup version 1.12.1. Vaadin 14 is using version 1.11.3.

I haven’t done a full test run with the new JSoup version, but at least the basic stuff seems to work and the reported issue can no longer be observed if I update pom.xml to explicitly use the newer version:

<dependency>
    <groupId>org.jsoup</groupId>
    <artifactId>jsoup</artifactId>
    <version>1.12.1</version>
</dependency>

If we for some reason cannot update Vaadin to use the newer JSoup version, then we could as a workaround add a dummy call to StringUtil.stringBuilder() right after building the bootstrap html string in the end of BootstrapHandler.synchronizedHandleRequest and WebComponentBootstrapHandler.writeBootstrapPage. This would cause the previous contents of the cached string builder to be cleared so that memory can be reclaimed immediately.

0reactions
m-emelchenkovcommented, Sep 26, 2019

@Legioth Thank you for informing me about your release plans!

Read more comments on GitHub >

github_iconTop Results From Across the Web

Class Index | Atlassian JIRA
A simple java bean that returns i18n name and description values. AbstractSimpleMapperValidator · AbstractSingleFieldType<T>, A abstract class that simplifies ...
Read more >
Release Notes - Vertuna WIKI - ConfiForms
Fixed issue with "Controlled vocabulary" option in multi-select fields ... Move/Copy attachments will be still possible on pages that have ConfiForms forms ...
Read more >
Search Results - CVE
The mission of the CVE® Program is to identify, define, and catalog publicly disclosed cybersecurity vulnerabilities.
Read more >
sitemap-questions-94.xml - Stack Overflow
https://stackoverflow.com/questions/13000/how-to-setup-site-wide-variables- ... -is-the-best-way-to-manage-duplicate-code-in-static-html-websites 2020-08-30 ...
Read more >
Index (Flow Server 4.0.0 API) - javadoc.io
Adds an action that will be run when all reflection caches are cleared. ... addDynamicImport(String) - Method in class com.vaadin.flow.component.page.Page.
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found