Tomcat 8 throwing - org.apache.catalina.webresources.Cache.getResource Unable to add the resource

CachingResourcesTomcat8

Caching Problem Overview


I have just upgraded Tomcat from version 7.0.52 to 8.0.14.

I am getting this for lots of static image files:

> org.apache.catalina.webresources.Cache.getResource Unable to add the > resource at [/base/1325/WA6144-150x112.jpg] to the cache because there > was insufficient free space available after evicting expired cache > entries - consider increasing the maximum size of the cache

I haven't specified any particular resource settings, and I didn't get this for 7.0.52.

I have found mention of this happening at startup in a bug report that was supposedly fixed. For me this is happening not at startup but constantly when the resource is requested.

Anybody else having this issue?

Trying to at least just disable the cache, but I cannot find an example of how to specify not to use the cache. The attributes have gone from the context in Tomcat version 8. Have tried adding a resource but cannot get the config right.

<Resource name="file" 
	cachingAllowed="false"
	className="org.apache.catalina.webresources.FileResourceSet"
/>	

Thanks.

Caching Solutions


Solution 1 - Caching

I had the same issue when upgrading from Tomcat 7 to 8: a continuous large flood of log warnings about cache.

1. Short Answer

Add this within the Context xml element of your $CATALINA_BASE/conf/context.xml:

<!-- The default value is 10240 kbytes, even when not added to context.xml.
So increase it high enough, until the problem disappears, for example set it to 
a value 5 times as high: 51200. -->
<Resources cacheMaxSize="51200" />

So the default is 10240 (10 mbyte), so set a size higher than this. Than tune for optimum settings where the warnings disappear. Note that the warnings may come back under higher traffic situations.

1.1 The cause (short explanation)

The problem is caused by Tomcat being unable to reach its target cache size due to cache entries that are less than the TTL of those entries. So Tomcat didn't have enough cache entries that it could expire, because they were too fresh, so it couldn't free enough cache and thus outputs warnings.

The problem didn't appear in Tomcat 7 because Tomcat 7 simply didn't output warnings in this situation. (Causing you and me to use poor cache settings without being notified.)

The problem appears when receiving a relative large amount of HTTP requests for resources (usually static) in a relative short time period compared to the size and TTL of the cache. If the cache is reaching its maximum (10mb by default) with more than 95% of its size with fresh cache entries (fresh means less than less than 5 seconds in cache), than you will get a warning message for each webResource that Tomcat tries to load in the cache.

1.2 Optional info

Use JMX if you need to tune cacheMaxSize on a running server without rebooting it.

The quickest fix would be to completely disable cache: <Resources cachingAllowed="false" />, but that's suboptimal, so increase cacheMaxSize as I just described.

2. Long Answer

2.1 Background information

A WebSource is a file or directory in a web application. For performance reasons, Tomcat can cache WebSources. The maximum of the static resource cache (all resources in total) is by default 10240 kbyte (10 mbyte). A webResource is loaded into the cache when the webResource is requested (for example when loading a static image), it's then called a cache entry. Every cache entry has a TTL (time to live), which is the time that the cache entry is allowed to stay in the cache. When the TTL expires, the cache entry is eligible to be removed from the cache. The default value of the cacheTTL is 5000 milliseconds (5 seconds).

There is more to tell about caching, but that is irrelevant for the problem.

2.2 The cause

The following code from the Cache class shows the caching policy in detail:

http://grepcode.com/file/repo1.maven.org/maven2/org.apache.tomcat/tomcat-catalina/8.0.24/org/apache/catalina/webresources/Cache.java#152">152</a>  // Content will not be cached but we still need metadata size
http://grepcode.com/file/repo1.maven.org/maven2/org.apache.tomcat/tomcat-catalina/8.0.24/org/apache/catalina/webresources/Cache.java#153">153</a> long delta = cacheEntry.http://grepcode.com/file/repo1.maven.org/maven2/org.apache.tomcat/tomcat-catalina/8.0.24/org/apache/catalina/webresources/CachedResource.java#CachedResource.getSize%28%29" title="org.apache.catalina.webresources.CachedResource.getSize() : long">getSize();
http://grepcode.com/file/repo1.maven.org/maven2/org.apache.tomcat/tomcat-catalina/8.0.24/org/apache/catalina/webresources/Cache.java#154">154</a> http://grepcode.com/file/repo1.maven.org/maven2/org.apache.tomcat/tomcat-catalina/8.0.24/org/apache/catalina/webresources/Cache.java#Cache.0size" title="AtomicLong size" class="hidden">size.http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/7u40-b43/java/util/concurrent/atomic/AtomicLong.java#AtomicLong.addAndGet%28long%29" title="java.util.concurrent.atomic.AtomicLong.addAndGet(long) : long">addAndGet(delta);
http://grepcode.com/file/repo1.maven.org/maven2/org.apache.tomcat/tomcat-catalina/8.0.24/org/apache/catalina/webresources/Cache.java#156">156</a> if (http://grepcode.com/file/repo1.maven.org/maven2/org.apache.tomcat/tomcat-catalina/8.0.24/org/apache/catalina/webresources/Cache.java#Cache.0size" title="AtomicLong size" class="hidden">size.http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/7u40-b43/java/util/concurrent/atomic/AtomicLong.java#AtomicLong.get%28%29" title="java.util.concurrent.atomic.AtomicLong.get() : long">get() > http://grepcode.com/file/repo1.maven.org/maven2/org.apache.tomcat/tomcat-catalina/8.0.24/org/apache/catalina/webresources/Cache.java#Cache.0maxSize" title="long maxSize" class="hidden">maxSize) {
http://grepcode.com/file/repo1.maven.org/maven2/org.apache.tomcat/tomcat-catalina/8.0.24/org/apache/catalina/webresources/Cache.java#157">157</a> // Process resources unordered for speed. Trades cache
http://grepcode.com/file/repo1.maven.org/maven2/org.apache.tomcat/tomcat-catalina/8.0.24/org/apache/catalina/webresources/Cache.java#158">158</a> // efficiency (younger entries may be evicted before older
http://grepcode.com/file/repo1.maven.org/maven2/org.apache.tomcat/tomcat-catalina/8.0.24/org/apache/catalina/webresources/Cache.java#159">159</a> // ones) for speed since this is on the critical path for
http://grepcode.com/file/repo1.maven.org/maven2/org.apache.tomcat/tomcat-catalina/8.0.24/org/apache/catalina/webresources/Cache.java#160">160</a> // request processing
http://grepcode.com/file/repo1.maven.org/maven2/org.apache.tomcat/tomcat-catalina/8.0.24/org/apache/catalina/webresources/Cache.java#161">161</a> long targetSize =
http://grepcode.com/file/repo1.maven.org/maven2/org.apache.tomcat/tomcat-catalina/8.0.24/org/apache/catalina/webresources/Cache.java#162">162</a> http://grepcode.com/file/repo1.maven.org/maven2/org.apache.tomcat/tomcat-catalina/8.0.24/org/apache/catalina/webresources/Cache.java#Cache.0maxSize" title="long maxSize" class="hidden">maxSize * (100 - http://grepcode.com/file/repo1.maven.org/maven2/org.apache.tomcat/tomcat-catalina/8.0.24/org/apache/catalina/webresources/Cache.java#Cache.0TARGET_FREE_PERCENT_GET" title="long TARGET_FREE_PERCENT_GET" class="hidden">TARGET_FREE_PERCENT_GET) / 100;
http://grepcode.com/file/repo1.maven.org/maven2/org.apache.tomcat/tomcat-catalina/8.0.24/org/apache/catalina/webresources/Cache.java#163">163</a> long newSize = http://grepcode.com/file/repo1.maven.org/maven2/org.apache.tomcat/tomcat-catalina/8.0.24/org/apache/catalina/webresources/Cache.java#Cache.evict%28long%2Cjava.util.Iterator%29" title="org.apache.catalina.webresources.Cache.evict(long,java.util.Iterator) : long">evict(
http://grepcode.com/file/repo1.maven.org/maven2/org.apache.tomcat/tomcat-catalina/8.0.24/org/apache/catalina/webresources/Cache.java#164">164</a> targetSize, http://grepcode.com/file/repo1.maven.org/maven2/org.apache.tomcat/tomcat-catalina/8.0.24/org/apache/catalina/webresources/Cache.java#Cache.0resourceCache" title="ConcurrentMap resourceCache" class="hidden">resourceCache.http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/7u40-b43/java/util/Map.java#Map.values%28%29" title="java.util.Map.values() : Collection">values().http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/7u40-b43/java/util/Collection.java#Collection.iterator%28%29" title="java.util.Collection.iterator() : Iterator">iterator());
http://grepcode.com/file/repo1.maven.org/maven2/org.apache.tomcat/tomcat-catalina/8.0.24/org/apache/catalina/webresources/Cache.java#165">165</a> if (newSize > http://grepcode.com/file/repo1.maven.org/maven2/org.apache.tomcat/tomcat-catalina/8.0.24/org/apache/catalina/webresources/Cache.java#Cache.0maxSize" title="long maxSize" class="hidden">maxSize) {
http://grepcode.com/file/repo1.maven.org/maven2/org.apache.tomcat/tomcat-catalina/8.0.24/org/apache/catalina/webresources/Cache.java#166">166</a> // Unable to create sufficient space for this resource
http://grepcode.com/file/repo1.maven.org/maven2/org.apache.tomcat/tomcat-catalina/8.0.24/org/apache/catalina/webresources/Cache.java#167">167</a> // Remove it from the cache
http://grepcode.com/file/repo1.maven.org/maven2/org.apache.tomcat/tomcat-catalina/8.0.24/org/apache/catalina/webresources/Cache.java#168">168</a> http://grepcode.com/file/repo1.maven.org/maven2/org.apache.tomcat/tomcat-catalina/8.0.24/org/apache/catalina/webresources/Cache.java#Cache.removeCacheEntry%28java.lang.String%29" title="org.apache.catalina.webresources.Cache.removeCacheEntry(java.lang.String) : void">removeCacheEntry(path);
http://grepcode.com/file/repo1.maven.org/maven2/org.apache.tomcat/tomcat-catalina/8.0.24/org/apache/catalina/webresources/Cache.java#169">169</a> http://grepcode.com/file/repo1.maven.org/maven2/org.apache.tomcat/tomcat-catalina/8.0.24/org/apache/catalina/webresources/Cache.java#Cache.0log" title="Log log" class="hidden">log.http://grepcode.com/file/repo1.maven.org/maven2/org.apache.tomcat/tomcat-juli/8.0.24/org/apache/juli/logging/Log.java#Log.warn%28java.lang.Object%29" title="org.apache.juli.logging.Log.warn(java.lang.Object) : void">warn(http://grepcode.com/file/repo1.maven.org/maven2/org.apache.tomcat/tomcat-catalina/8.0.24/org/apache/catalina/webresources/Cache.java#Cache.0sm" title="StringManager sm" class="hidden">sm.http://grepcode.com/file/repo1.maven.org/maven2/org.apache.tomcat/tomcat-util/8.0.24/org/apache/tomcat/util/res/StringManager.java#StringManager.getString%28java.lang.String%2Cjava.lang.Object%5B%5D%29" title="org.apache.tomcat.util.res.StringManager.getString(java.lang.String,java.lang.Object[]) : String">getString("cache.addFail", path));
http://grepcode.com/file/repo1.maven.org/maven2/org.apache.tomcat/tomcat-catalina/8.0.24/org/apache/catalina/webresources/Cache.java#170">170</a> }
http://grepcode.com/file/repo1.maven.org/maven2/org.apache.tomcat/tomcat-catalina/8.0.24/org/apache/catalina/webresources/Cache.java#171">171</a> }
When loading a webResource, the code calculates the new size of the cache. If the calculated size is larger than the default maximum size, than one or more cached entries have to be removed, otherwise the new size will exceed the maximum. So the code will calculate a "targetSize", which is the size the cache wants to stay under (as an optimum), which is by default 95% of the maximum. In order to reach this targetSize, entries have to be removed/evicted from the cache. This is done using the following code:

http://grepcode.com/file/repo1.maven.org/maven2/org.apache.tomcat/tomcat-catalina/8.0.24/org/apache/catalina/webresources/Cache.java#215">215</a>  private long evict(long targetSize, http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/7u40-b43/java/util/Iterator.java#Iterator" title="java.util.Iterator">Iterator<http://grepcode.com/file/repo1.maven.org/maven2/org.apache.tomcat/tomcat-catalina/8.0.24/org/apache/catalina/webresources/CachedResource.java#CachedResource" title="org.apache.catalina.webresources.CachedResource">CachedResource> iter) {
http://grepcode.com/file/repo1.maven.org/maven2/org.apache.tomcat/tomcat-catalina/8.0.24/org/apache/catalina/webresources/Cache.java#217">217</a> long now = System.http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/7u40-b43/java/lang/System.java#System.currentTimeMillis%28%29" title="java.lang.System.currentTimeMillis() : long">currentTimeMillis();
http://grepcode.com/file/repo1.maven.org/maven2/org.apache.tomcat/tomcat-catalina/8.0.24/org/apache/catalina/webresources/Cache.java#219">219</a> long newSize = http://grepcode.com/file/repo1.maven.org/maven2/org.apache.tomcat/tomcat-catalina/8.0.24/org/apache/catalina/webresources/Cache.java#Cache.0size" title="AtomicLong size" class="hidden">size.http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/7u40-b43/java/util/concurrent/atomic/AtomicLong.java#AtomicLong.get%28%29" title="java.util.concurrent.atomic.AtomicLong.get() : long">get();
http://grepcode.com/file/repo1.maven.org/maven2/org.apache.tomcat/tomcat-catalina/8.0.24/org/apache/catalina/webresources/Cache.java#221">221</a> while (newSize > targetSize && iter.http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/7u40-b43/java/util/Iterator.java#Iterator.hasNext%28%29" title="java.util.Iterator.hasNext() : boolean">hasNext()) {
http://grepcode.com/file/repo1.maven.org/maven2/org.apache.tomcat/tomcat-catalina/8.0.24/org/apache/catalina/webresources/Cache.java#222">222</a> http://grepcode.com/file/repo1.maven.org/maven2/org.apache.tomcat/tomcat-catalina/8.0.24/org/apache/catalina/webresources/CachedResource.java#CachedResource" title="org.apache.catalina.webresources.CachedResource">CachedResource resource = iter.http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/7u40-b43/java/util/Iterator.java#Iterator.next%28%29" title="java.util.Iterator.next() : CachedResource">next();
http://grepcode.com/file/repo1.maven.org/maven2/org.apache.tomcat/tomcat-catalina/8.0.24/org/apache/catalina/webresources/Cache.java#224">224</a> // Don't expire anything that has been checked within the TTL
http://grepcode.com/file/repo1.maven.org/maven2/org.apache.tomcat/tomcat-catalina/8.0.24/org/apache/catalina/webresources/Cache.java#225">225</a> if (resource.http://grepcode.com/file/repo1.maven.org/maven2/org.apache.tomcat/tomcat-catalina/8.0.24/org/apache/catalina/webresources/CachedResource.java#CachedResource.getNextCheck%28%29" title="org.apache.catalina.webresources.CachedResource.getNextCheck() : long">getNextCheck() > now) {
http://grepcode.com/file/repo1.maven.org/maven2/org.apache.tomcat/tomcat-catalina/8.0.24/org/apache/catalina/webresources/Cache.java#226">226</a> continue;
http://grepcode.com/file/repo1.maven.org/maven2/org.apache.tomcat/tomcat-catalina/8.0.24/org/apache/catalina/webresources/Cache.java#227">227</a> }
http://grepcode.com/file/repo1.maven.org/maven2/org.apache.tomcat/tomcat-catalina/8.0.24/org/apache/catalina/webresources/Cache.java#229">229</a> // Remove the entry from the cache
http://grepcode.com/file/repo1.maven.org/maven2/org.apache.tomcat/tomcat-catalina/8.0.24/org/apache/catalina/webresources/Cache.java#230">230</a> http://grepcode.com/file/repo1.maven.org/maven2/org.apache.tomcat/tomcat-catalina/8.0.24/org/apache/catalina/webresources/Cache.java#Cache.removeCacheEntry%28java.lang.String%29" title="org.apache.catalina.webresources.Cache.removeCacheEntry(java.lang.String) : void">removeCacheEntry(resource.http://grepcode.com/file/repo1.maven.org/maven2/org.apache.tomcat/tomcat-catalina/8.0.24/org/apache/catalina/webresources/CachedResource.java#CachedResource.getWebappPath%28%29" title="org.apache.catalina.webresources.CachedResource.getWebappPath() : String">getWebappPath());
http://grepcode.com/file/repo1.maven.org/maven2/org.apache.tomcat/tomcat-catalina/8.0.24/org/apache/catalina/webresources/Cache.java#232">232</a> newSize = http://grepcode.com/file/repo1.maven.org/maven2/org.apache.tomcat/tomcat-catalina/8.0.24/org/apache/catalina/webresources/Cache.java#Cache.0size" title="AtomicLong size" class="hidden">size.http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/7u40-b43/java/util/concurrent/atomic/AtomicLong.java#AtomicLong.get%28%29" title="java.util.concurrent.atomic.AtomicLong.get() : long">get();
http://grepcode.com/file/repo1.maven.org/maven2/org.apache.tomcat/tomcat-catalina/8.0.24/org/apache/catalina/webresources/Cache.java#233">233</a> }
http://grepcode.com/file/repo1.maven.org/maven2/org.apache.tomcat/tomcat-catalina/8.0.24/org/apache/catalina/webresources/Cache.java#235">235</a> return newSize;
http://grepcode.com/file/repo1.maven.org/maven2/org.apache.tomcat/tomcat-catalina/8.0.24/org/apache/catalina/webresources/Cache.java#236">236</a> }

So a cache entry is removed when its TTL is expired and the targetSize hasn't been reached yet.

After the attempt to free cache by evicting cache entries, the code will do:

http://grepcode.com/file/repo1.maven.org/maven2/org.apache.tomcat/tomcat-catalina/8.0.24/org/apache/catalina/webresources/Cache.java#165">165</a>  if (newSize > http://grepcode.com/file/repo1.maven.org/maven2/org.apache.tomcat/tomcat-catalina/8.0.24/org/apache/catalina/webresources/Cache.java#Cache.0maxSize" title="long maxSize" class="hidden">maxSize) {
http://grepcode.com/file/repo1.maven.org/maven2/org.apache.tomcat/tomcat-catalina/8.0.24/org/apache/catalina/webresources/Cache.java#166">166</a> // Unable to create sufficient space for this resource
http://grepcode.com/file/repo1.maven.org/maven2/org.apache.tomcat/tomcat-catalina/8.0.24/org/apache/catalina/webresources/Cache.java#167">167</a> // Remove it from the cache
http://grepcode.com/file/repo1.maven.org/maven2/org.apache.tomcat/tomcat-catalina/8.0.24/org/apache/catalina/webresources/Cache.java#168">168</a> http://grepcode.com/file/repo1.maven.org/maven2/org.apache.tomcat/tomcat-catalina/8.0.24/org/apache/catalina/webresources/Cache.java#Cache.removeCacheEntry%28java.lang.String%29" title="org.apache.catalina.webresources.Cache.removeCacheEntry(java.lang.String) : void">removeCacheEntry(path);
http://grepcode.com/file/repo1.maven.org/maven2/org.apache.tomcat/tomcat-catalina/8.0.24/org/apache/catalina/webresources/Cache.java#169">169</a> http://grepcode.com/file/repo1.maven.org/maven2/org.apache.tomcat/tomcat-catalina/8.0.24/org/apache/catalina/webresources/Cache.java#Cache.0log" title="Log log" class="hidden">log.http://grepcode.com/file/repo1.maven.org/maven2/org.apache.tomcat/tomcat-juli/8.0.24/org/apache/juli/logging/Log.java#Log.warn%28java.lang.Object%29" title="org.apache.juli.logging.Log.warn(java.lang.Object) : void">warn(http://grepcode.com/file/repo1.maven.org/maven2/org.apache.tomcat/tomcat-catalina/8.0.24/org/apache/catalina/webresources/Cache.java#Cache.0sm" title="StringManager sm" class="hidden">sm.http://grepcode.com/file/repo1.maven.org/maven2/org.apache.tomcat/tomcat-util/8.0.24/org/apache/tomcat/util/res/StringManager.java#StringManager.getString%28java.lang.String%2Cjava.lang.Object%5B%5D%29" title="org.apache.tomcat.util.res.StringManager.getString(java.lang.String,java.lang.Object[]) : String">getString("cache.addFail", path));
http://grepcode.com/file/repo1.maven.org/maven2/org.apache.tomcat/tomcat-catalina/8.0.24/org/apache/catalina/webresources/Cache.java#170">170</a> }

So if after the attempt to free cache, the size still exceeds the maximum, it will show the warning message about being unable to free:

cache.addFail=Unable to add the resource at [{0}] to the cache for web application [{1}] because there was insufficient free space available after evicting expired cache entries - consider increasing the maximum size of the cache

2.3 The problem

So as the warning message says, the problem is

> insufficient free space available after evicting expired cache entries - consider increasing the maximum size of the cache

If your web application loads a lot of uncached webResources (about maximum of cache, by default 10mb) within a short time (5 seconds), then you'll get the warning.

The confusing part is that Tomcat 7 didn't show the warning. This is simply caused by this Tomcat 7 code:

http://grepcode.com/file/repo1.maven.org/maven2/org.apache.tomcat/tomcat-catalina/7.0.0/org/apache/naming/resources/ProxyDirContext.java#1606">1606</a>  // Add new entry to cache
http://grepcode.com/file/repo1.maven.org/maven2/org.apache.tomcat/tomcat-catalina/7.0.0/org/apache/naming/resources/ProxyDirContext.java#1607">1607</a> synchronized (http://grepcode.com/file/repo1.maven.org/maven2/org.apache.tomcat/tomcat-catalina/7.0.0/org/apache/naming/resources/ProxyDirContext.java#ProxyDirContext.0cache" title="ResourceCache cache" class="hidden">cache) {
http://grepcode.com/file/repo1.maven.org/maven2/org.apache.tomcat/tomcat-catalina/7.0.0/org/apache/naming/resources/ProxyDirContext.java#1608">1608</a> // Check cache size, and remove elements if too big
http://grepcode.com/file/repo1.maven.org/maven2/org.apache.tomcat/tomcat-catalina/7.0.0/org/apache/naming/resources/ProxyDirContext.java#1609">1609</a> if ((http://grepcode.com/file/repo1.maven.org/maven2/org.apache.tomcat/tomcat-catalina/7.0.0/org/apache/naming/resources/ProxyDirContext.java#ProxyDirContext.0cache" title="ResourceCache cache" class="hidden">cache.http://grepcode.com/file/repo1.maven.org/maven2/org.apache.tomcat/tomcat-catalina/7.0.0/org/apache/naming/resources/ResourceCache.java#ResourceCache.lookup%28java.lang.String%29" title="org.apache.naming.resources.ResourceCache.lookup(java.lang.String) : CacheEntry">lookup(name) == null) && http://grepcode.com/file/repo1.maven.org/maven2/org.apache.tomcat/tomcat-catalina/7.0.0/org/apache/naming/resources/ProxyDirContext.java#ProxyDirContext.0cache" title="ResourceCache cache" class="hidden">cache.http://grepcode.com/file/repo1.maven.org/maven2/org.apache.tomcat/tomcat-catalina/7.0.0/org/apache/naming/resources/ResourceCache.java#ResourceCache.allocate%28int%29" title="org.apache.naming.resources.ResourceCache.allocate(int) : boolean">allocate(entry.size)) {
http://grepcode.com/file/repo1.maven.org/maven2/org.apache.tomcat/tomcat-catalina/7.0.0/org/apache/naming/resources/ProxyDirContext.java#1610">1610</a> http://grepcode.com/file/repo1.maven.org/maven2/org.apache.tomcat/tomcat-catalina/7.0.0/org/apache/naming/resources/ProxyDirContext.java#ProxyDirContext.0cache" title="ResourceCache cache" class="hidden">cache.http://grepcode.com/file/repo1.maven.org/maven2/org.apache.tomcat/tomcat-catalina/7.0.0/org/apache/naming/resources/ResourceCache.java#ResourceCache.load%28org.apache.naming.resources.CacheEntry%29" title="org.apache.naming.resources.ResourceCache.load(org.apache.naming.resources.CacheEntry) : void">load(entry);
http://grepcode.com/file/repo1.maven.org/maven2/org.apache.tomcat/tomcat-catalina/7.0.0/org/apache/naming/resources/ProxyDirContext.java#1611">1611</a> }
http://grepcode.com/file/repo1.maven.org/maven2/org.apache.tomcat/tomcat-catalina/7.0.0/org/apache/naming/resources/ProxyDirContext.java#1612">1612</a> }
combined with:
http://grepcode.com/file/repo1.maven.org/maven2/org.apache.tomcat/tomcat-catalina/7.0.0/org/apache/naming/resources/ResourceCache.java#231">231</a>  while (toFree > 0) {
http://grepcode.com/file/repo1.maven.org/maven2/org.apache.tomcat/tomcat-catalina/7.0.0/org/apache/naming/resources/ResourceCache.java#232">232</a> if (attempts == http://grepcode.com/file/repo1.maven.org/maven2/org.apache.tomcat/tomcat-catalina/7.0.0/org/apache/naming/resources/ResourceCache.java#ResourceCache.0maxAllocateIterations" title="int maxAllocateIterations" class="hidden">maxAllocateIterations) {
http://grepcode.com/file/repo1.maven.org/maven2/org.apache.tomcat/tomcat-catalina/7.0.0/org/apache/naming/resources/ResourceCache.java#233">233</a> // Give up, no changes are made to the current cache
http://grepcode.com/file/repo1.maven.org/maven2/org.apache.tomcat/tomcat-catalina/7.0.0/org/apache/naming/resources/ResourceCache.java#234">234</a> return false;
http://grepcode.com/file/repo1.maven.org/maven2/org.apache.tomcat/tomcat-catalina/7.0.0/org/apache/naming/resources/ResourceCache.java#235">235</a> }

So Tomcat 7 simply doesn't output any warning at all when it's unable to free cache, whereas Tomcat 8 will output a warning.

So if you are using Tomcat 8 with the same default caching configuration as Tomcat 7, and you got warnings in Tomcat 8, than your (and mine) caching settings of Tomcat 7 were performing poorly without warning.

2.4 Solutions

There are multiple solutions:

  1. Increase cache (recommended)
  2. Lower the TTL (not recommended)
  3. Suppress cache log warnings (not recommended)
  4. Disable cache

As described here: http://tomcat.apache.org/tomcat-8.0-doc/config/resources.html

By adding <Resources cacheMaxSize="XXXXX" /> within the Context element in $CATALINA_BASE/conf/context.xml, where "XXXXX" stands for an increased cache size, specified in kbytes. The default is 10240 (10 mbyte), so set a size higher than this.

You'll have to tune for optimum settings. Note that the problem may come back when you suddenly have an increase in traffic/resource requests.

To avoid having to restart the server every time you want to try a new cache size, you can change it without restarting by using JMX.

To enable JMX, add this to $CATALINA_BASE/conf/server.xml within the Server element: <Listener className="org.apache.catalina.mbeans.JmxRemoteLifecycleListener" rmiRegistryPortPlatform="6767" rmiServerPortPlatform="6768" /> and download catalina-jmx-remote.jar from https://tomcat.apache.org/download-80.cgi and put it in $CATALINA_HOME/lib. Then use jConsole (shipped by default with the Java JDK) to connect over JMX to the server and look through the settings for settings to increase the cache size while the server is running. Changes in these settings should take affect immediately.

Lower the cacheTtl value by something lower than 5000 milliseconds and tune for optimal settings.

For example: <Resources cacheTtl="2000" />

This comes effectively down to having and filling a cache in ram without using it.

Configure logging to disable the logger for org.apache.catalina.webresources.Cache.

For more info about logging in Tomcat: http://tomcat.apache.org/tomcat-8.0-doc/logging.html

2.4.4. Disable cache

You can disable the cache by setting cachingAllowed to false. <Resources cachingAllowed="false" />

Although I can remember that in a beta version of Tomcat 8, I was using JMX to disable the cache. (Not sure why exactly, but there may be a problem with disabling the cache via server.xml.)

Solution 2 - Caching

In your $CATALINA_BASE/conf/context.xml add block below before </Context>

<Resources cachingAllowed="true" cacheMaxSize="100000" />

For more information: http://tomcat.apache.org/tomcat-8.0-doc/config/resources.html

Solution 3 - Caching

You have more static resources that the cache has room for. You can do one of the following:

  • Increase the size of the cache
  • Decrease the TTL for the cache
  • Disable caching

For more details see the documentation for these configuration options.

Solution 4 - Caching

This isn’t a solution in the sense that it doesn’t resolve the conditions which cause the message to appear in the logs, but the message can be suppressed by appending the following to conf/logging.properties:

org.apache.catalina.webresources.Cache.level = SEVERE

This filters out the “Unable to add the resource” logs, which are at level WARNING.

In my view a WARNING is not necessarily an error that needs to be addressed, but rather can be ignored if desired.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
Questioniainmac999View Question on Stackoverflow
Solution 1 - CachingDevabcView Answer on Stackoverflow
Solution 2 - CachingDestroyicaView Answer on Stackoverflow
Solution 3 - CachingMark ThomasView Answer on Stackoverflow
Solution 4 - CachingGeoffrey BoothView Answer on Stackoverflow