Tomcat 8 throwing - org.apache.catalina.webresources.Cache.getResource Unable to add the resource
CachingResourcesTomcat8Caching 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 sizeWhen 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#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> }
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 cachecombined with:
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> }
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:
- Increase cache (recommended)
- Lower the TTL (not recommended)
- Suppress cache log warnings (not recommended)
- Disable cache
2.4.1. Increase cache (recommended)
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.
2.4.2. Lower the TTL (not recommended)
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.
2.4.3. Suppress cache log warnings (not recommended)
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.