Bug 57619 - Memory consumption
Summary: Memory consumption
Status: RESOLVED FIXED
Alias: None
Product: Tomcat 8
Classification: Unclassified
Component: Catalina (show other bugs)
Version: 8.0.18
Hardware: PC Linux
: P2 enhancement (vote)
Target Milestone: ----
Assignee: Tomcat Developers Mailing List
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2015-02-23 09:29 UTC by Jaroslav Kamenik
Modified: 2018-01-05 14:44 UTC (History)
0 users



Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Jaroslav Kamenik 2015-02-23 09:29:12 UTC
I have inspected running tomcat containing two webapps with Eclipse Memory Analyser and have found lots of same instances of String. For example

14300x "jar"
3100x "/home/xxxx/workspace/.metadata/.plugins/org.eclipse.wst.server.core/tmp2/wtpwebapps/XXXXXXXX/WEB-INF/lib/AppXXXXXXX.jar"

lots of similar long paths to other jars.

It is just few MBs of memory, but it could help a little to merge them somehow.
Comment 1 Mark Thomas 2015-02-23 22:32:46 UTC
No analysis provided to suggest the proposed merging is even possible. (Chances are it isn't without a lot of complexity else the JVM would have already done it.)
Comment 2 Christopher Schultz 2015-02-24 20:00:43 UTC
I tracked-down a bunch of similar issues in our own application several years ago, and it turned out that the application framework (Struts 1, in our case), was the culprit. We never found that Tomcat was a significant source of "duplicate" strings.
Comment 3 Dmitri Blinov 2017-11-07 07:45:50 UTC
I have found the similar simptoms that the multiple "jar" strings are allocated by tomcat WebappClassLoader. The problem stems from usage of java.net.URL(String spec) constructor for ResourceEntry. The java.net.URL(String) parses the source and splits the "scheme" part, and by forcibly converting it toLowerString a separate copy of "jar" string is created for each new ResourceEntry. The problem can be solved by using different java.net.URL(String protocol, String host, int port, String file) constructor, where "jar" can by passed as a constant which could be shared by all instances of created URL classes. 

I have created a small home test for Tomcat 7.0.82, which by means of visualvm/heapdump showed that "jar" strings are realy shared among different instances of URLs.

The code for example for Tomcat 7.0.82 is located in org.apache.tomcat.buf.UriUtil.java, the commented lines are from previous version:

    public static URL buildJarUrl(String fileUrlString, String entryPath) throws MalformedURLException {
        String safeString = makeSafeForJarUrl(fileUrlString);
        StringBuilder sb = new StringBuilder();
        // sb.append("jar:");
        sb.append(safeString);
        sb.append("!/");
        if (entryPath != null) {
            sb.append(makeSafeForJarUrl(entryPath));
        }
        // return new URL(sb.toString());
        return new URL("jar", null, -1, sb.toString());
    }
Comment 4 Mark Thomas 2018-01-05 14:44:08 UTC
Thanks for the patch - it looks reasonable to me. My testing shows 7.0.x benefits from this more, possibly due to the resources refactoring in 8.0.x onwards.

Fixed in:
- trunk for 9.0.3 onwards
- 8.5.x for 8.5.25 onwards
- 8.0.x for 8.0.49 onwards
- 7.0.x for 7.0.84 onwards