You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by Arvind Talari <ar...@veeva.com> on 2020/06/05 22:15:42 UTC

NullPointerException when loading class

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