Author: davsclaus Date: Fri Oct 5 07:03:59 2012 New Revision: 1394386 URL: http://svn.apache.org/viewvc?rev=1394386&view=rev Log: CAMEL-5675: Using a LRUWeakCache instead of soft to reclaim the cache eager as we dont want to keep the cache around, and cause classloader unload issues as we store references to Class and Method in the cache.
Added: camel/trunk/camel-core/src/main/java/org/apache/camel/util/LRUWeakCache.java - copied, changed from r1394362, camel/trunk/camel-core/src/main/java/org/apache/camel/util/LRUSoftCache.java Modified: camel/trunk/camel-core/src/main/java/org/apache/camel/management/MBeanInfoAssembler.java camel/trunk/camel-core/src/main/java/org/apache/camel/util/IntrospectionSupport.java camel/trunk/camel-core/src/main/java/org/apache/camel/util/LRUSoftCache.java camel/trunk/camel-core/src/test/resources/log4j.properties Modified: camel/trunk/camel-core/src/main/java/org/apache/camel/management/MBeanInfoAssembler.java URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/management/MBeanInfoAssembler.java?rev=1394386&r1=1394385&r2=1394386&view=diff ============================================================================== --- camel/trunk/camel-core/src/main/java/org/apache/camel/management/MBeanInfoAssembler.java (original) +++ camel/trunk/camel-core/src/main/java/org/apache/camel/management/MBeanInfoAssembler.java Fri Oct 5 07:03:59 2012 @@ -37,7 +37,8 @@ import org.apache.camel.api.management.M import org.apache.camel.api.management.ManagedOperation; import org.apache.camel.api.management.ManagedResource; import org.apache.camel.util.IntrospectionSupport; -import org.apache.camel.util.LRUSoftCache; +import org.apache.camel.util.LRUCache; +import org.apache.camel.util.LRUWeakCache; import org.apache.camel.util.ObjectHelper; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -52,7 +53,9 @@ public class MBeanInfoAssembler implemen private static final Logger LOG = LoggerFactory.getLogger(MBeanInfoAssembler.class); // use a cache to speedup gathering JMX MBeanInfo for known classes - private final Map<Class<?>, MBeanAttributesAndOperations> cache = new LRUSoftCache<Class<?>, MBeanAttributesAndOperations>(1000); + // use a weak cache as we dont want the cache to keep around as it reference classes + // which could prevent classloader to unload classes if being referenced from this cache + private final LRUCache<Class<?>, MBeanAttributesAndOperations> cache = new LRUWeakCache<Class<?>, MBeanAttributesAndOperations>(1000); @Override public void start() throws Exception { @@ -61,6 +64,9 @@ public class MBeanInfoAssembler implemen @Override public void stop() throws Exception { + if (LOG.isDebugEnabled()) { + LOG.debug("Clearing cache[size={}, hits={}, misses={}]", new Object[]{cache.size(), cache.getHits(), cache.getMisses()}); + } cache.clear(); } Modified: camel/trunk/camel-core/src/main/java/org/apache/camel/util/IntrospectionSupport.java URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/util/IntrospectionSupport.java?rev=1394386&r1=1394385&r2=1394386&view=diff ============================================================================== --- camel/trunk/camel-core/src/main/java/org/apache/camel/util/IntrospectionSupport.java (original) +++ camel/trunk/camel-core/src/main/java/org/apache/camel/util/IntrospectionSupport.java Fri Oct 5 07:03:59 2012 @@ -56,7 +56,10 @@ public final class IntrospectionSupport private static final Pattern GETTER_PATTERN = Pattern.compile("(get|is)[A-Z].*"); private static final Pattern SETTER_PATTERN = Pattern.compile("set[A-Z].*"); private static final List<Method> EXCLUDED_METHODS = new ArrayList<Method>(); - private static final Map<Class<?>, ClassInfo> CACHE = new LRUSoftCache<Class<?>, ClassInfo>(1000); + // use a cache to speedup introspecting for known classes during startup + // use a weak cache as we dont want the cache to keep around as it reference classes + // which could prevent classloader to unload classes if being referenced from this cache + private static final LRUCache<Class<?>, ClassInfo> CACHE = new LRUWeakCache<Class<?>, ClassInfo>(1000); static { // exclude all java.lang.Object methods as we dont want to invoke them @@ -96,6 +99,9 @@ public final class IntrospectionSupport * This implementation will clear its introspection cache. */ public static void stop() { + if (LOG.isDebugEnabled()) { + LOG.debug("Clearing cache[size={}, hits={}, misses={}]", new Object[]{CACHE.size(), CACHE.getHits(), CACHE.getMisses()}); + } CACHE.clear(); } Modified: camel/trunk/camel-core/src/main/java/org/apache/camel/util/LRUSoftCache.java URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/util/LRUSoftCache.java?rev=1394386&r1=1394385&r2=1394386&view=diff ============================================================================== --- camel/trunk/camel-core/src/main/java/org/apache/camel/util/LRUSoftCache.java (original) +++ camel/trunk/camel-core/src/main/java/org/apache/camel/util/LRUSoftCache.java Fri Oct 5 07:03:59 2012 @@ -48,6 +48,7 @@ import java.util.Set; * for the existence of a value without catering for the soft references. * * @see LRUCache + * @see LRUWeakCache */ public class LRUSoftCache<K, V> extends LRUCache<K, V> { private static final long serialVersionUID = 1L; Copied: camel/trunk/camel-core/src/main/java/org/apache/camel/util/LRUWeakCache.java (from r1394362, camel/trunk/camel-core/src/main/java/org/apache/camel/util/LRUSoftCache.java) URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/util/LRUWeakCache.java?p2=camel/trunk/camel-core/src/main/java/org/apache/camel/util/LRUWeakCache.java&p1=camel/trunk/camel-core/src/main/java/org/apache/camel/util/LRUSoftCache.java&r1=1394362&r2=1394386&rev=1394386&view=diff ============================================================================== --- camel/trunk/camel-core/src/main/java/org/apache/camel/util/LRUSoftCache.java (original) +++ camel/trunk/camel-core/src/main/java/org/apache/camel/util/LRUWeakCache.java Fri Oct 5 07:03:59 2012 @@ -16,7 +16,7 @@ */ package org.apache.camel.util; -import java.lang.ref.SoftReference; +import java.lang.ref.WeakReference; import java.util.ArrayList; import java.util.Collection; import java.util.LinkedHashSet; @@ -24,10 +24,10 @@ import java.util.Map; import java.util.Set; /** - * A Least Recently Used Cache which uses {@link SoftReference}. + * A Least Recently Used Cache which uses {@link java.lang.ref.WeakReference}. * <p/> - * This implementation uses {@link java.lang.ref.SoftReference} for stored values in the cache, to support the JVM - * when it wants to reclaim objects when it's running out of memory. Therefore this implementation does + * This implementation uses {@link java.lang.ref.WeakReference} for stored values in the cache, to support the JVM + * when it wants to reclaim objects for example during garbage collection. Therefore this implementation does * not support <b>all</b> the {@link java.util.Map} methods. * <p/> * The following methods is <b>only</b> be be used: @@ -48,36 +48,37 @@ import java.util.Set; * for the existence of a value without catering for the soft references. * * @see LRUCache + * @see LRUSoftCache */ -public class LRUSoftCache<K, V> extends LRUCache<K, V> { +public class LRUWeakCache<K, V> extends LRUCache<K, V> { private static final long serialVersionUID = 1L; - public LRUSoftCache(int maximumCacheSize) { + public LRUWeakCache(int maximumCacheSize) { super(maximumCacheSize); } - public LRUSoftCache(int initialCapacity, int maximumCacheSize) { + public LRUWeakCache(int initialCapacity, int maximumCacheSize) { super(initialCapacity, maximumCacheSize); } @Override @SuppressWarnings("unchecked") public V put(K key, V value) { - SoftReference<V> put = new SoftReference<V>(value); - SoftReference<V> prev = (SoftReference<V>) super.put(key, (V) put); + WeakReference<V> put = new WeakReference<V>(value); + WeakReference<V> prev = (WeakReference<V>) super.put(key, (V) put); return prev != null ? prev.get() : null; } @Override @SuppressWarnings("unchecked") public V get(Object o) { - SoftReference<V> ref = (SoftReference<V>) super.get(o); + WeakReference<V> ref = (WeakReference<V>) super.get(o); return ref != null ? ref.get() : null; } @Override public void putAll(Map<? extends K, ? extends V> map) { - for (Map.Entry<? extends K, ? extends V> entry : map.entrySet()) { + for (Entry<? extends K, ? extends V> entry : map.entrySet()) { put(entry.getKey(), entry.getValue()); } } @@ -85,7 +86,7 @@ public class LRUSoftCache<K, V> extends @Override @SuppressWarnings("unchecked") public V remove(Object o) { - SoftReference<V> ref = (SoftReference<V>) super.remove(o); + WeakReference<V> ref = (WeakReference<V>) super.remove(o); return ref != null ? ref.get() : null; } @@ -93,9 +94,9 @@ public class LRUSoftCache<K, V> extends @SuppressWarnings("unchecked") public Collection<V> values() { // return a copy of all the active values - Collection<SoftReference<V>> col = (Collection<SoftReference<V>>) super.values(); + Collection<WeakReference<V>> col = (Collection<WeakReference<V>>) super.values(); Collection<V> answer = new ArrayList<V>(); - for (SoftReference<V> ref : col) { + for (WeakReference<V> ref : col) { V value = ref.get(); if (value != null) { answer.add(value); @@ -109,7 +110,7 @@ public class LRUSoftCache<K, V> extends // only count as a size if there is a value int size = 0; for (V value : super.values()) { - SoftReference<?> ref = (SoftReference<?>) value; + WeakReference<?> ref = (WeakReference<?>) value; if (ref != null && ref.get() != null) { size++; } @@ -130,15 +131,15 @@ public class LRUSoftCache<K, V> extends } @Override - public Set<Map.Entry<K, V>> entrySet() { - Set<Map.Entry<K, V>> original = super.entrySet(); + public Set<Entry<K, V>> entrySet() { + Set<Entry<K, V>> original = super.entrySet(); // must use a copy to avoid concurrent modifications and be able to get/set value using // the soft reference so the returned set is without the soft reference, and thus is // use able for the caller to use - Set<Map.Entry<K, V>> answer = new LinkedHashSet<Map.Entry<K, V>>(original.size()); - for (final Map.Entry<K, V> entry : original) { - Map.Entry<K, V> view = new Map.Entry<K, V>() { + Set<Entry<K, V>> answer = new LinkedHashSet<Entry<K, V>>(original.size()); + for (final Entry<K, V> entry : original) { + Entry<K, V> view = new Entry<K, V>() { @Override public K getKey() { return entry.getKey(); @@ -147,15 +148,15 @@ public class LRUSoftCache<K, V> extends @Override @SuppressWarnings("unchecked") public V getValue() { - SoftReference<V> ref = (SoftReference<V>) entry.getValue(); + WeakReference<V> ref = (WeakReference<V>) entry.getValue(); return ref != null ? ref.get() : null; } @Override @SuppressWarnings("unchecked") public V setValue(V v) { - V put = (V) new SoftReference<V>(v); - SoftReference<V> prev = (SoftReference<V>) entry.setValue(put); + V put = (V) new WeakReference<V>(v); + WeakReference<V> prev = (WeakReference<V>) entry.setValue(put); return prev != null ? prev.get() : null; } }; @@ -167,6 +168,6 @@ public class LRUSoftCache<K, V> extends @Override public String toString() { - return "LRUSoftCache@" + ObjectHelper.getIdentityHashCode(this); + return "LRUWeakCache@" + ObjectHelper.getIdentityHashCode(this); } } \ No newline at end of file Modified: camel/trunk/camel-core/src/test/resources/log4j.properties URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/test/resources/log4j.properties?rev=1394386&r1=1394385&r2=1394386&view=diff ============================================================================== --- camel/trunk/camel-core/src/test/resources/log4j.properties (original) +++ camel/trunk/camel-core/src/test/resources/log4j.properties Fri Oct 5 07:03:59 2012 @@ -21,7 +21,7 @@ log4j.rootLogger=INFO, file #log4j.logger.org.apache.camel.impl.converter=WARN -log4j.logger.org.apache.camel.management=WARN +#log4j.logger.org.apache.camel.management=WARN log4j.logger.org.apache.camel.impl.DefaultPackageScanClassResolver=WARN #log4j.logger.org.apache.camel.impl.converter.DefaultTypeConverter=TRACE #log4j.logger.org.apache.camel.impl.converter=DEBUG