Bug 56293

Summary: WebappClassLoader does not cache META-INF/services which leads to performance issues
Product: Tomcat 7 Reporter: Michael Thiele <michael.thiele>
Component: CatalinaAssignee: Tomcat Developers Mailing List <dev>
Status: RESOLVED FIXED    
Severity: normal    
Priority: P2    
Version: 7.0.28   
Target Milestone: ---   
Hardware: PC   
OS: All   
Attachments: Example .war and maven projects for the META-INF/services caching problem

Description Michael Thiele 2014-03-20 09:53:08 UTC
Since Tomcat 7.0.28, the WebappClassLoader does not cache any resources on the classpath except .class and .properties files (see https://issues.apache.org/bugzilla/show_bug.cgi?id=53081).
This leads to a massive performance problem in applications that contain .jars on the classpath that use the ServiceLoader mechanism of Java 6 to bind concrete XML readers and writers to their respective interfaces, since every time the concrete instance is loaded, the WebappClassLoader has to open the .jar to read which concrete implementation is used.
A possible solution might be that caching is enabled for all resources that reside in the META-INF/services folder.
Comment 1 Mark Thomas 2014-03-20 11:18:21 UTC
Neither the problem nor the solution appear to be that simple. Looking at the ServiceLoader code, the contents of META-INF/services aren't read using the method where the caching was removed.

Can you put together a simple test case that demonstrates this issue?
Comment 2 Michael Thiele 2014-03-20 15:41:56 UTC
Created attachment 31417 [details]
Example .war and maven projects for the META-INF/services caching problem

I have built a small example of what happens in our code.
Deployment in Tomcat 7.0.27 and 7.0.28 should render different results (time needed is increased by factor 10 with META-INF/services) when accessing the root path, e.g., http://localhost:8080/tomcat.caching-0.0.1-SNAPSHOT/.
Comment 3 Mark Thomas 2014-03-20 17:01:20 UTC
Thanks for the test case. It appears that the ServiceLoader code isn't used and it is clear that the code path where caching was removed is used.

I agree that caching the contents META-INF/services id probably the way to go but I think there will need to be some form of limit just in case there is a large file there for some strange reason. I'm looking into a fix now.
Comment 4 Mark Thomas 2014-03-23 20:44:32 UTC
This has been fixed in 8.0.x for 8.0.5 onwards and in 7.0.x for 7.0.53 onwards.