If you look inside WebappClassLoader, once a resource is loaded and a ResourceEntry is allocated for it it is never freed. Now say a user references a large image on my webapp once 10 hours ago, I'm stuck with that memory loss indefinately. My website is very image oriented (a lot of large images) and it is quite painful to keep those unused images around forever. I keep on running into OutOfMemoryErrors. We should be able to configure reasonable idle settings. For example, I'd like for image resources to be freed if they've been idle for over 30 minutes.
How about filing sensible bug reports rather than continuously waste people's time with non existent corner cases ? Obviously there are one million ways to write broken webapps.
Remm, this isn't a problem with my webapp. This is a problem with Tomcat. WebappClassLoader disregards the context cache settings. That is the problem. I can't even configure its behavior.
Look Remy, I'm not trying to fight with you but what I'm saying is this... resourceEntries is only referenced by WebappClassLoader.java (I scanned the entire source-code tree) and within that file, entries are added but never removed. It does not respect the configuration settings outlined here: http://jakarta.apache.org/tomcat/tomcat-5.5-doc/config/context.html Specifically, cacheMaxSize, cacheTTL.
(In reply to comment #3) > Look Remy, I'm not trying to fight with you but what I'm saying is this... > > resourceEntries is only referenced by WebappClassLoader.java (I scanned the > entire source-code tree) and within that file, entries are added but never > removed. It does not respect the configuration settings outlined here: > http://jakarta.apache.org/tomcat/tomcat-5.5-doc/config/context.html > > Specifically, cacheMaxSize, cacheTTL. These attributes are not for controlling the classloader behavior.
Ok, then humbly request that you allow me to file this RFE. Is there any good reason to not allow the classloader to deallocate idle resource cache entries? If a large JAR entry was accessed accessed a few hours ago, why should it remain cached in memory?
Classloaders are nearly all of the time meant to load applications and their needed resources. As a result, all the said resources will have the same lifecycle. You are trying to use the Tomcat classloader to do something else. For that kind of usage, you should use a custom classloader implementation, or (better) use a loading mechanism which actually suit your needs.
Yes, but how many ClassLoaders keep a cache around forever with no maximum size or idle detection? At the very least you should be using SoftReferences here, which have been around since JDK 1.2 and have been specifically designated for caches. Webapps are rarely short-lived which makes this problem even worse. I would be perfectly fine with SoftReferences with no configuration settings. Can you make this modification?
How come classloaders hold class definitions forever until they are destroyed ?
Remy, I really don't understand what your objection is all about. What is lost by modifying the code to use SoftReferences? Classes can be kept around forever with a minimal memory impact. Caching the underlying resources on the other hand is a totally different matter as they are *much* bigger. I don't think anything is lost by using SoftReferences.
(In reply to comment #9) > Remy, I really don't understand what your objection is all about. What is lost > by modifying the code to use SoftReferences? Do you really understand SoftReferences? Quite a lot of the time, a SoftReference will be GC'ed as soon as the JVM has to do its first full GC. For most of our applications, we've found that SoftReferences are GC'ed on an average within minutes or even seconds of losing their last hard reference.
Shankar, From the Javadoc: "Virtual machine implementations are, however, encouraged to bias against clearing recently-created or recently-used soft references." and "Thus a sophisticated cache can, for example, prevent its most recently used entries from being discarded by keeping strong referents to those entries, leaving the remaining entries to be discarded at the discretion of the garbage collector." Memory has to come from somewhere. There is absolutely nothing wrong with resource cache entries being removed by GC if it just so happens that these references are used less often than others in the pool. I understand your concerns, but I think we can all agree on the following use-case: if a large image resource has not been accessed in over 12 hours, it makes perfect sense to allow it to be garbage collected. If you really want to guarantee that resources will remain cached for a minimum of X minutes, simply maintain a hard reference to them and after X minutes remove the hard reference leaving only SoftReferences in place. I've used this many times in my own code and it works beautifully.