Hi All, We have upgraded our Tomcat version to 9.0.27 from 8.0.42, since then we have been pretty frequently running into the below NullPointerException when our application classes get loaded, we believe this is due a concurrency issue (more details below). java.lang.NullPointerException at org.apache.catalina.webresources.CachedResource.getURL(CachedResource.java:317) at org.apache.catalina.webresources.FileResource.getCodeBase(FileResource.java:277) at org.apache.catalina.loader.WebappClassLoaderBase.findClassInternal(WebappClassLoaderBase.java:2350) at org.apache.catalina.loader.WebappClassLoaderBase.findClass(WebappClassLoaderBase.java:865) at org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1334) at org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1188)
Our Environment: Tomcat Version: 9.0.27. Our application classes exploded to WEB-INF/classes. Our Investigation: To troubleshoot the issue, we have looked at code in https://github.com/apache/tomcat/blob/9.0.27/java/org/apache/catalina/webresources/Cache.java and https://github.com/apache/tomcat/blob/9.0.27/java/org/apache/catalina/webresources/CachedResource.java#L70, and it appears that we would run into this error if CachedResource is used when org.apache.catalina.webresources.CachedResource#webResource isn't initialized (i.e. stays null). Upon further debugging and viewing code in https://github.com/apache/tomcat/blob/9.0.27/java/org/apache/catalina/webresources/Cache.java#L59, it seems like it is possible that CachedResource could be used when its #webResource isn't initialized when two threads concurrently ask for the same resource but each with a different value for the boolean useClassLoaderResources. Consider this for example with 2 threads calling into Cache#getResource(String path, boolean useClassLoaderResources) for the same resource but with two different values for useClassLoaderResources and the resource is not in cache, both threads end up at line https://github.com/apache/tomcat/blob/9.0.27/java/org/apache/catalina/webresources/Cache.java#L82, then: Thread 1: useClassLoaderResources=true A new CachedResource is created at line https://github.com/apache/tomcat/blob/9.0.27/java/org/apache/catalina/webresources/Cache.java#L77 and put into cache at line https://github.com/apache/tomcat/blob/9.0.27/java/org/apache/catalina/webresources/Cache.java#L82 but CachedResource#validateResource (where CachedResource#webResource is initialized) is not called yet, this would happen at line https://github.com/apache/tomcat/blob/9.0.27/java/org/apache/catalina/webresources/Cache.java#L87 . Thread 2: useClassLoaderResources=false A new CachedResource is created at line https://github.com/apache/tomcat/blob/9.0.27/java/org/apache/catalina/webresources/Cache.java#L77 <https://github.com/apache/tomcat/blob/9.0.27/java/org/apache/catalina/webresources/Cache.java#L137> but finds the CachedResource in the cache (put in by the above thread) at line https://github.com/apache/tomcat/blob/9.0.27/java/org/apache/catalina/webresources/Cache.java#L82 and calls CachedResource#validateResource at line https://github.com/apache/tomcat/blob/9.0.27/java/org/apache/catalina/webresources/Cache.java#L112 , but #validateResource doesn't do anything and returns because useClassLoaderResources is false, and so CachedResource#webResource remains uninitialized. Assuming that Thread 1 hasn't initialized #webResource yet, when this thread (Thread 2) calls into CachedResource#getURL we would run into this error. Looks like the changes in the revision https://svn.apache.org/viewvc?view=revision&revision=1831828 are related. This seems like a concurrency issue, and we haven't seen this addressed in newer versions (from the changelog here https://ci.apache.org/projects/tomcat/tomcat9/docs/changelog.html) Request: Your prompt help on moving this forward to resolution is greatly appreciated. I can log a defect for this if you agree. Regards, Arvind