[jboss-cvs] JBossAS SVN: r99279 - in projects/jboss-classpool/trunk/classpool/src: main/java/org/jboss/classpool/domain and 3 other directories.
jboss-cvs-commits at lists.jboss.org
jboss-cvs-commits at lists.jboss.org
Tue Jan 12 07:53:33 EST 2010
Author: kabir.khan at jboss.com
Date: 2010-01-12 07:53:31 -0500 (Tue, 12 Jan 2010)
New Revision: 99279
Added:
projects/jboss-classpool/trunk/classpool/src/main/java/org/jboss/classpool/base/CtClassCache.java
projects/jboss-classpool/trunk/classpool/src/main/java/org/jboss/classpool/base/CtClassCacheFactory.java
projects/jboss-classpool/trunk/classpool/src/main/java/org/jboss/classpool/base/SecurityActions.java
projects/jboss-classpool/trunk/classpool/src/test/java/org/jboss/test/classpool/support/MockCachePolicy.java
projects/jboss-classpool/trunk/classpool/src/test/java/org/jboss/test/classpool/test/RealCtCacheTestCase.java
projects/jboss-classpool/trunk/classpool/src/test/java/org/jboss/test/classpool/test/SimpleCtCacheTestCase.java
Modified:
projects/jboss-classpool/trunk/classpool/src/main/java/org/jboss/classpool/base/AbstractParentDelegationStrategy.java
projects/jboss-classpool/trunk/classpool/src/main/java/org/jboss/classpool/base/BaseClassPool.java
projects/jboss-classpool/trunk/classpool/src/main/java/org/jboss/classpool/base/BaseClassPoolDomain.java
projects/jboss-classpool/trunk/classpool/src/main/java/org/jboss/classpool/base/DefaultParentDelegationStrategy.java
projects/jboss-classpool/trunk/classpool/src/main/java/org/jboss/classpool/base/ParentDelegationStrategy.java
projects/jboss-classpool/trunk/classpool/src/main/java/org/jboss/classpool/domain/ClassPoolDomain.java
projects/jboss-classpool/trunk/classpool/src/main/java/org/jboss/classpool/domain/ClassPoolToClassPoolDomainAdapter.java
projects/jboss-classpool/trunk/classpool/src/main/java/org/jboss/classpool/plugins/DelegatingClassPool.java
Log:
[JBREFLECT-92] Add caching to classpools and domains
Modified: projects/jboss-classpool/trunk/classpool/src/main/java/org/jboss/classpool/base/AbstractParentDelegationStrategy.java
===================================================================
--- projects/jboss-classpool/trunk/classpool/src/main/java/org/jboss/classpool/base/AbstractParentDelegationStrategy.java 2010-01-12 09:25:34 UTC (rev 99278)
+++ projects/jboss-classpool/trunk/classpool/src/main/java/org/jboss/classpool/base/AbstractParentDelegationStrategy.java 2010-01-12 12:53:31 UTC (rev 99279)
@@ -100,4 +100,9 @@
}
this.domain = domain;
}
+
+ public int getParentModCount()
+ {
+ return parent.getModCount();
+ }
}
Modified: projects/jboss-classpool/trunk/classpool/src/main/java/org/jboss/classpool/base/BaseClassPool.java
===================================================================
--- projects/jboss-classpool/trunk/classpool/src/main/java/org/jboss/classpool/base/BaseClassPool.java 2010-01-12 09:25:34 UTC (rev 99278)
+++ projects/jboss-classpool/trunk/classpool/src/main/java/org/jboss/classpool/base/BaseClassPool.java 2010-01-12 12:53:31 UTC (rev 99279)
@@ -162,7 +162,8 @@
logger.trace(classname + " could not be found from " + this, e);
throw e;
-} }
+ }
+ }
@Override
public CtClass get0(String classname, boolean useCache) throws NotFoundException
Modified: projects/jboss-classpool/trunk/classpool/src/main/java/org/jboss/classpool/base/BaseClassPoolDomain.java
===================================================================
--- projects/jboss-classpool/trunk/classpool/src/main/java/org/jboss/classpool/base/BaseClassPoolDomain.java 2010-01-12 09:25:34 UTC (rev 99278)
+++ projects/jboss-classpool/trunk/classpool/src/main/java/org/jboss/classpool/base/BaseClassPoolDomain.java 2010-01-12 12:53:31 UTC (rev 99279)
@@ -23,6 +23,7 @@
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
@@ -47,7 +48,11 @@
private final ParentDelegationStrategy parentDelegationStrategy;
private final ReadWriteLock lock = new ReentrantReadWriteLock();
-
+
+ private volatile int modCount;
+
+ private volatile int parentModCount;
+
public BaseClassPoolDomain(String domainName, ClassPoolDomain parent, boolean parentFirst)
{
this(domainName,
@@ -63,6 +68,7 @@
this.domainName = domainName;
this.parentDelegationStrategy = parentDelegationStrategy;
parentDelegationStrategy.setDomain(this);
+ this.parentModCount = parentDelegationStrategy.getParentModCount();
if (logger.isTraceEnabled()) logger.trace("Created " + this + " parentDelegationStrategy:" + parentDelegationStrategy);
}
@@ -75,6 +81,8 @@
{
if (logger.isTraceEnabled()) logger.trace(this + " adding pool " + pool);
delegatingPools.add(pool);
+ parentModCount = parentDelegationStrategy.getParentModCount();
+ modCount++;
}
}
finally
@@ -89,7 +97,11 @@
try
{
if (logger.isTraceEnabled()) logger.trace(this + " removing pool " + pool);
- delegatingPools.remove(pool);
+ if (delegatingPools.remove(pool))
+ {
+ parentModCount = parentDelegationStrategy.getParentModCount();
+ modCount++;
+ }
}
finally
{
@@ -97,9 +109,36 @@
}
}
+ public int getModCount()
+ {
+ //Check if the parent mod count has changed (pool was added/removed in parent)
+ System.out.println(domainName + " " + parentModCount + ":" + parentDelegationStrategy.getParentModCount());
+ if (parentModCount < parentDelegationStrategy.getParentModCount())
+ {
+ lockWrite();
+ try
+ {
+ int parentCount = parentDelegationStrategy.getParentModCount();
+ if (parentCount > parentModCount)
+ {
+ this.parentModCount = parentCount;
+ return ++modCount;
+ }
+ }
+ finally
+ {
+ unlockWrite();
+ }
+ }
+
+ return modCount;
+ }
+
+
public CtClass getCachedOrCreate(DelegatingClassPool initiatingPool, String classname, boolean create)
{
boolean trace = logger.isTraceEnabled();
+
String resourceName = ClassLoaderUtils.getResourceName(classname);
CtClass clazz = getCachedOrCreate(initiatingPool, classname, resourceName, create, trace);
@@ -108,6 +147,7 @@
{
clazz = getCachedOrCreateFromPoolParent(initiatingPool, classname, create, trace);
}
+
return clazz;
}
@@ -190,4 +230,5 @@
{
lock.writeLock().unlock();
}
+
}
Added: projects/jboss-classpool/trunk/classpool/src/main/java/org/jboss/classpool/base/CtClassCache.java
===================================================================
--- projects/jboss-classpool/trunk/classpool/src/main/java/org/jboss/classpool/base/CtClassCache.java (rev 0)
+++ projects/jboss-classpool/trunk/classpool/src/main/java/org/jboss/classpool/base/CtClassCache.java 2010-01-12 12:53:31 UTC (rev 99279)
@@ -0,0 +1,72 @@
+/*
+* JBoss, Home of Professional Open Source.
+* Copyright 2006, Red Hat Middleware LLC, and individual contributors
+* as indicated by the @author tags. See the copyright.txt file in the
+* distribution for a full listing of individual contributors.
+*
+* This is free software; you can redistribute it and/or modify it
+* under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of
+* the License, or (at your option) any later version.
+*
+* This software is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this software; if not, write to the Free
+* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+package org.jboss.classpool.base;
+
+import javassist.CtClass;
+
+import org.jboss.util.CachePolicy;
+
+/**
+ *
+ * @author <a href="kabir.khan at jboss.com">Kabir Khan</a>
+ * @version $Revision: 1.1 $
+ */
+public class CtClassCache
+{
+ private final CachePolicy policy;
+
+ private volatile int viewId;
+
+ CtClassCache(CachePolicy policy)
+ {
+ this.policy = policy;
+ }
+
+ public void put(String classname, CtClass clazz)
+ {
+ synchronized (policy)
+ {
+ //Something strange is going on with the policy, sometimes it says duplicate entries even when I test with a peek/get, so always remove the existing entry
+ policy.remove(classname);
+ policy.insert(classname, clazz);
+ }
+ }
+
+ public CtClass get(String classname, int viewId)
+ {
+ if (viewId != this.viewId)
+ {
+ synchronized(policy)
+ {
+ invalidate();
+ if (viewId > this.viewId)
+ this.viewId = viewId;
+ }
+ }
+ return (CtClass)policy.get(classname);
+ }
+
+ public void invalidate()
+ {
+ policy.flush();
+ }
+}
Added: projects/jboss-classpool/trunk/classpool/src/main/java/org/jboss/classpool/base/CtClassCacheFactory.java
===================================================================
--- projects/jboss-classpool/trunk/classpool/src/main/java/org/jboss/classpool/base/CtClassCacheFactory.java (rev 0)
+++ projects/jboss-classpool/trunk/classpool/src/main/java/org/jboss/classpool/base/CtClassCacheFactory.java 2010-01-12 12:53:31 UTC (rev 99279)
@@ -0,0 +1,218 @@
+/*
+* JBoss, Home of Professional Open Source.
+* Copyright 2006, Red Hat Middleware LLC, and individual contributors
+* as indicated by the @author tags. See the copyright.txt file in the
+* distribution for a full listing of individual contributors.
+*
+* This is free software; you can redistribute it and/or modify it
+* under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of
+* the License, or (at your option) any later version.
+*
+* This software is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this software; if not, write to the Free
+* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+package org.jboss.classpool.base;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Modifier;
+import java.util.Properties;
+
+import org.jboss.logging.Logger;
+import org.jboss.util.CachePolicy;
+import org.jboss.util.LRUCachePolicy;
+import org.jboss.util.TimedCachePolicy;
+
+/**
+ *
+ * @author <a href="kabir.khan at jboss.com">Kabir Khan</a>
+ * @version $Revision: 1.1 $
+ */
+public class CtClassCacheFactory
+{
+ private static final Logger log = Logger.getLogger(Logger.class);
+
+ public static final String POLICY_CLASS = "org.jboss.classpool.policy";
+
+ public static final String TIMED_POLICY_LIFETIME = "org.jboss.classpool.policy.lifetime";
+
+ public static final String TIMED_POLICY_RESOLUTION = "org.jboss.classpool.policy.resolution";
+
+ public static final String LRU_POLICY_MIN = "org.jboss.classpool.policy.min";
+
+ public static final String LRU_POLICY_MAX = "org.jboss.classpool.policy.max";
+
+ public static final int DEFAULT_TIMED_POLICY_LIFETIME = 200;
+
+ public static final int DEFAULT_TIMED_POLICY_RESOLUTION = 3;
+
+ public static final int DEFAULT_LRU_POLICY_MIN = 10;
+
+ public static final int DEFAULT_LRU_POLICY_MAX = 100;
+
+ private volatile Class<? extends CachePolicy> policyClass;
+
+ private volatile int lifetime;
+
+ private volatile int resolution;
+
+ private volatile int min;
+
+ private volatile int max;
+
+ public static CtClassCacheFactory createFromProperties()
+ {
+ return createFromProperties(System.getProperties());
+ }
+
+ public static CtClassCacheFactory createFromProperties(Properties properties)
+ {
+ CtClassCacheFactory initializer = new CtClassCacheFactory();
+ String policy = properties.getProperty(POLICY_CLASS, TimedCachePolicy.class.getName());
+ try
+ {
+ Class<?> clazz = Class.forName(policy);
+ if (CachePolicy.class.isAssignableFrom(clazz) == false)
+ throw new IllegalStateException(clazz + " is not an instance of " + CachePolicy.class.getName());
+ else
+ initializer.policyClass = (Class<? extends CachePolicy>)clazz;
+ }
+ catch(Exception e)
+ {
+ throw new IllegalStateException("Could not load policy class " + policy, e);
+ }
+
+ if (TimedCachePolicy.class.isAssignableFrom(initializer.policyClass))
+ {
+ initializer.lifetime = parsePropertyIntoInteger(properties, TIMED_POLICY_LIFETIME, DEFAULT_TIMED_POLICY_LIFETIME);
+ initializer.resolution = parsePropertyIntoInteger(properties, TIMED_POLICY_RESOLUTION, DEFAULT_TIMED_POLICY_RESOLUTION);
+ warnUnusedParameters(properties, initializer.policyClass, LRU_POLICY_MIN, LRU_POLICY_MAX);
+ }
+ else if (LRUCachePolicy.class.isAssignableFrom(initializer.policyClass))
+ {
+ initializer.min = parsePropertyIntoInteger(properties, LRU_POLICY_MIN, DEFAULT_LRU_POLICY_MIN);
+ initializer.max = parsePropertyIntoInteger(properties, LRU_POLICY_MAX, DEFAULT_LRU_POLICY_MAX);
+ warnUnusedParameters(properties, initializer.policyClass, TIMED_POLICY_LIFETIME, TIMED_POLICY_RESOLUTION);
+ }
+ else
+ {
+ try
+ {
+ Constructor<?> ctor = initializer.policyClass.getConstructor();
+ if (!Modifier.isPublic(ctor.getModifiers()))
+ throw new IllegalStateException("Unknown policy class " + initializer.policyClass.getName() + " has a default constructor, but it is not public");
+ }
+ catch(NoSuchMethodException e)
+ {
+ throw new IllegalStateException("Unknown policy class " + initializer.policyClass.getName() + " does not have a default constructor");
+ }
+ }
+ return initializer;
+ }
+
+ public CtClassCache createCache()
+ {
+ CachePolicy policy = null;
+ if (policyClass == TimedCachePolicy.class)
+ policy = new TimedCachePolicy(lifetime, true, resolution);
+ else if (policyClass == LRUCachePolicy.class)
+ policy = new LRUCachePolicy(min, max);
+ else
+ {
+ try
+ {
+ policy = policyClass.newInstance();
+ }
+ catch(Exception e)
+ {
+ throw new IllegalStateException("Could not instantiate " + policyClass.getName(), e);
+ }
+ }
+
+ try
+ {
+ policy.create();
+ policy.start();
+ }
+ catch(Exception e)
+ {
+ throw new IllegalStateException("Error starting domain cache", e);
+ }
+ return new CtClassCache(policy);
+ }
+
+ /**
+ * Get the policyClass
+ * @return the policyClass
+ */
+ public Class<? extends CachePolicy> getPolicyClass()
+ {
+ return policyClass;
+ }
+
+ /**
+ * Get the lifetime
+ * @return the lifetime
+ */
+ public int getLifetime()
+ {
+ return lifetime;
+ }
+
+ /**
+ * Get the resolution
+ * @return the resolution
+ */
+ public int getResolution()
+ {
+ return resolution;
+ }
+
+ /**
+ * Get the min
+ * @return the min
+ */
+ public int getMin()
+ {
+ return min;
+ }
+
+ /**
+ * Get the max
+ * @return the max
+ */
+ public int getMax()
+ {
+ return max;
+ }
+
+ private static int parsePropertyIntoInteger(Properties properties, String key, int defaultValue)
+ {
+ try
+ {
+ return Integer.valueOf(properties.getProperty(key, String.valueOf(defaultValue)));
+ }
+ catch(NumberFormatException e)
+ {
+ throw new IllegalStateException("The value " + properties.getProperty(key) + " for '" + key + "' is not a number");
+ }
+ }
+
+ private static void warnUnusedParameters(Properties properties, Class<?> clazz, String...keys)
+ {
+ for (String key : keys)
+ {
+ if (properties.getProperty(key) != null)
+ {
+ log.warn("Ignoring unrecognized property " + key + " for policy class" + clazz);
+ }
+ }
+ }
+}
Modified: projects/jboss-classpool/trunk/classpool/src/main/java/org/jboss/classpool/base/DefaultParentDelegationStrategy.java
===================================================================
--- projects/jboss-classpool/trunk/classpool/src/main/java/org/jboss/classpool/base/DefaultParentDelegationStrategy.java 2010-01-12 09:25:34 UTC (rev 99278)
+++ projects/jboss-classpool/trunk/classpool/src/main/java/org/jboss/classpool/base/DefaultParentDelegationStrategy.java 2010-01-12 12:53:31 UTC (rev 99279)
@@ -52,4 +52,5 @@
if (logger.isTraceEnabled()) logger.trace(this + " " + getDomain() + " isParentAfter " + isParentAfter);
return isParentAfter;
}
+
}
Modified: projects/jboss-classpool/trunk/classpool/src/main/java/org/jboss/classpool/base/ParentDelegationStrategy.java
===================================================================
--- projects/jboss-classpool/trunk/classpool/src/main/java/org/jboss/classpool/base/ParentDelegationStrategy.java 2010-01-12 09:25:34 UTC (rev 99278)
+++ projects/jboss-classpool/trunk/classpool/src/main/java/org/jboss/classpool/base/ParentDelegationStrategy.java 2010-01-12 12:53:31 UTC (rev 99279)
@@ -41,4 +41,6 @@
boolean isParentBefore(String classname);
boolean isParentAfter(String classname);
+
+ int getParentModCount();
}
Added: projects/jboss-classpool/trunk/classpool/src/main/java/org/jboss/classpool/base/SecurityActions.java
===================================================================
--- projects/jboss-classpool/trunk/classpool/src/main/java/org/jboss/classpool/base/SecurityActions.java (rev 0)
+++ projects/jboss-classpool/trunk/classpool/src/main/java/org/jboss/classpool/base/SecurityActions.java 2010-01-12 12:53:31 UTC (rev 99279)
@@ -0,0 +1,84 @@
+/*
+* JBoss, Home of Professional Open Source.
+* Copyright 2006, Red Hat Middleware LLC, and individual contributors
+* as indicated by the @author tags. See the copyright.txt file in the
+* distribution for a full listing of individual contributors.
+*
+* This is free software; you can redistribute it and/or modify it
+* under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of
+* the License, or (at your option) any later version.
+*
+* This software is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this software; if not, write to the Free
+* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+package org.jboss.classpool.base;
+
+import java.lang.reflect.Constructor;
+import java.security.AccessController;
+import java.security.PrivilegedActionException;
+import java.security.PrivilegedExceptionAction;
+
+/**
+ *
+ * @author <a href="kabir.khan at jboss.com">Kabir Khan</a>
+ * @version $Revision: 1.1 $
+ */
+class SecurityActions
+{
+ Constructor<?> getConstructor(final Class<?> clazz, final Class<?>...parameterTypes) throws NoSuchMethodException
+ {
+ if (System.getSecurityManager() == null)
+ return clazz.getConstructor(parameterTypes);
+
+ try
+ {
+ return AccessController.doPrivileged(new PrivilegedExceptionAction<Constructor<?>>()
+ {
+
+ public Constructor<?> run() throws Exception
+ {
+ return clazz.getConstructor(parameterTypes);
+ }
+ });
+ }
+ catch(PrivilegedActionException e)
+ {
+ if (e.getCause() instanceof NoSuchMethodException)
+ throw (NoSuchMethodException)e.getCause();
+ throw new RuntimeException(e.getCause());
+ }
+ }
+
+ Object newInstance(final Class<?> clazz) throws Exception
+ {
+ if (System.getSecurityManager() == null)
+ return clazz.newInstance();
+
+ try
+ {
+ return AccessController.doPrivileged(new PrivilegedExceptionAction<Object>()
+ {
+
+ public Object run() throws Exception
+ {
+ return clazz.newInstance();
+ }
+ });
+ }
+ catch(PrivilegedActionException e)
+ {
+ if (e.getCause() instanceof Exception)
+ throw (Exception)e.getCause();
+ throw new RuntimeException(e.getCause());
+ }
+ }
+
+}
Modified: projects/jboss-classpool/trunk/classpool/src/main/java/org/jboss/classpool/domain/ClassPoolDomain.java
===================================================================
--- projects/jboss-classpool/trunk/classpool/src/main/java/org/jboss/classpool/domain/ClassPoolDomain.java 2010-01-12 09:25:34 UTC (rev 99278)
+++ projects/jboss-classpool/trunk/classpool/src/main/java/org/jboss/classpool/domain/ClassPoolDomain.java 2010-01-12 12:53:31 UTC (rev 99279)
@@ -37,4 +37,5 @@
public void removeClassPool(DelegatingClassPool pool);
public CtClass getCachedOrCreate(DelegatingClassPool initiatingPool, String classname, boolean create);
public CtClass getCachedOrCreate(DelegatingClassPool initiatingPool, String classname, String resourceName, boolean create, boolean trace);
+ public int getModCount();
}
\ No newline at end of file
Modified: projects/jboss-classpool/trunk/classpool/src/main/java/org/jboss/classpool/domain/ClassPoolToClassPoolDomainAdapter.java
===================================================================
--- projects/jboss-classpool/trunk/classpool/src/main/java/org/jboss/classpool/domain/ClassPoolToClassPoolDomainAdapter.java 2010-01-12 09:25:34 UTC (rev 99278)
+++ projects/jboss-classpool/trunk/classpool/src/main/java/org/jboss/classpool/domain/ClassPoolToClassPoolDomainAdapter.java 2010-01-12 12:53:31 UTC (rev 99279)
@@ -97,4 +97,9 @@
{
return "ClassPoolToDomainAdapter[" + System.identityHashCode(this) + " " + pool.toString() + "]";
}
+
+ public int getModCount()
+ {
+ return 0;
+ }
}
Modified: projects/jboss-classpool/trunk/classpool/src/main/java/org/jboss/classpool/plugins/DelegatingClassPool.java
===================================================================
--- projects/jboss-classpool/trunk/classpool/src/main/java/org/jboss/classpool/plugins/DelegatingClassPool.java 2010-01-12 09:25:34 UTC (rev 99278)
+++ projects/jboss-classpool/trunk/classpool/src/main/java/org/jboss/classpool/plugins/DelegatingClassPool.java 2010-01-12 12:53:31 UTC (rev 99279)
@@ -22,16 +22,18 @@
package org.jboss.classpool.plugins;
+import javassist.ClassPool;
+import javassist.CtClass;
+import javassist.NotFoundException;
+import javassist.scopedpool.ScopedClassPoolRepository;
+
import org.jboss.classpool.base.BaseClassPool;
+import org.jboss.classpool.base.CtClassCacheFactory;
+import org.jboss.classpool.base.CtClassCache;
import org.jboss.classpool.domain.AbstractClassPoolDomain;
import org.jboss.classpool.domain.ClassPoolDomain;
import org.jboss.classpool.helpers.ClassLoaderUtils;
-import javassist.ClassPool;
-import javassist.CtClass;
-import javassist.NotFoundException;
-import javassist.scopedpool.ScopedClassPoolRepository;
-
/**
* Base class for classpools backed by a domain
*
@@ -44,6 +46,10 @@
private volatile boolean closed;
+ private final CtClassCache cachedLookups;
+
+ private static final CtClassCacheFactory factory = CtClassCacheFactory.createFromProperties();
+
public DelegatingClassPool(ClassPoolDomain domain, ClassLoader cl, ClassPool parent, ScopedClassPoolRepository repository)
{
super(cl, parent, repository);
@@ -58,6 +64,7 @@
if (logger.isTraceEnabled()) logger.trace(this + " domain:" + this);
this.domain = domain;
this.domain.addClassPool(this);
+ cachedLookups = factory.createCache();
}
public CtClass loadLocally(String classname, String resourceName, boolean create)
@@ -85,8 +92,16 @@
*/
@Override
//TODO KABIR was synchronized - I don't see why apart from that the standard javassist.ClassPool implementation was synchronized?
- public CtClass get0(String classname, boolean useCache) throws NotFoundException
+ public final CtClass get0(String classname, boolean useCache) throws NotFoundException
{
+ //KABIR Made final just to make sure that cached lookups are only handled in one place.
+ CtClass cachedLookup = cachedLookups.get(classname, domain.getModCount());
+ if (cachedLookup != null)
+ {
+ logger.trace(classname + " was found in the cache of " + this);
+ return cachedLookup;
+ }
+
if (isGeneratedClass(classname))
{
return null;
@@ -101,6 +116,8 @@
//https://jira.jboss.org/jira/browse/JBCL-92
clazz = loadLocally(classname, ClassLoaderUtils.getResourceName(classname), true);
}
+
+ cachedLookups.put(classname, clazz);
return clazz;
}
Added: projects/jboss-classpool/trunk/classpool/src/test/java/org/jboss/test/classpool/support/MockCachePolicy.java
===================================================================
--- projects/jboss-classpool/trunk/classpool/src/test/java/org/jboss/test/classpool/support/MockCachePolicy.java (rev 0)
+++ projects/jboss-classpool/trunk/classpool/src/test/java/org/jboss/test/classpool/support/MockCachePolicy.java 2010-01-12 12:53:31 UTC (rev 99279)
@@ -0,0 +1,111 @@
+/*
+* JBoss, Home of Professional Open Source.
+* Copyright 2006, Red Hat Middleware LLC, and individual contributors
+* as indicated by the @author tags. See the copyright.txt file in the
+* distribution for a full listing of individual contributors.
+*
+* This is free software; you can redistribute it and/or modify it
+* under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of
+* the License, or (at your option) any later version.
+*
+* This software is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this software; if not, write to the Free
+* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+package org.jboss.test.classpool.support;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.jboss.util.CachePolicy;
+
+/**
+ *
+ * @author <a href="kabir.khan at jboss.com">Kabir Khan</a>
+ * @version $Revision: 1.1 $
+ */
+public class MockCachePolicy implements CachePolicy
+{
+ public static List<MockCachePolicy> policies = new ArrayList<MockCachePolicy>();
+
+ Map<Object, Object> map = new HashMap<Object, Object>();
+
+ List<Object> wasCachedClasses = new ArrayList<Object>();
+
+ public MockCachePolicy()
+ {
+ policies.add(this);
+ }
+
+ public void create() throws Exception
+ {
+ }
+
+ public void destroy()
+ {
+ map.clear();
+ }
+
+ public void flush()
+ {
+ map.clear();
+ }
+
+ public Object get(Object key)
+ {
+ Object o = map.get(key);
+ if (o != null)
+ {
+ wasCachedClasses.add(key);
+ }
+ return o;
+ }
+
+ public boolean wasCached(String clazz)
+ {
+ return wasCachedClasses.contains(clazz);
+ }
+
+ public void clearWasCachedClassses()
+ {
+ wasCachedClasses.clear();
+ }
+
+ public void insert(Object key, Object object)
+ {
+ map.put(key, object);
+ }
+
+ public Object peek(Object key)
+ {
+ return map.get(key);
+ }
+
+ public void remove(Object key)
+ {
+ map.remove(key);
+ }
+
+ public int size()
+ {
+ return map.size();
+ }
+
+ public void start() throws Exception
+ {
+ }
+
+ public void stop()
+ {
+ }
+
+}
Added: projects/jboss-classpool/trunk/classpool/src/test/java/org/jboss/test/classpool/test/RealCtCacheTestCase.java
===================================================================
--- projects/jboss-classpool/trunk/classpool/src/test/java/org/jboss/test/classpool/test/RealCtCacheTestCase.java (rev 0)
+++ projects/jboss-classpool/trunk/classpool/src/test/java/org/jboss/test/classpool/test/RealCtCacheTestCase.java 2010-01-12 12:53:31 UTC (rev 99279)
@@ -0,0 +1,193 @@
+/*
+* JBoss, Home of Professional Open Source.
+* Copyright 2006, Red Hat Middleware LLC, and individual contributors
+* as indicated by the @author tags. See the copyright.txt file in the
+* distribution for a full listing of individual contributors.
+*
+* This is free software; you can redistribute it and/or modify it
+* under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of
+* the License, or (at your option) any later version.
+*
+* This software is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this software; if not, write to the Free
+* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+package org.jboss.test.classpool.test;
+
+import static org.jboss.test.classpool.support.SupportArchives.JAR_A_URL;
+import static org.jboss.test.classpool.support.SupportArchives.JAR_B_URL;
+import static org.jboss.test.classpool.support.SupportClasses.CLASS_A;
+import static org.jboss.test.classpool.support.SupportClasses.CLASS_B;
+import javassist.ClassPool;
+import javassist.CtClass;
+
+import org.jboss.classpool.base.CtClassCacheFactory;
+import org.jboss.classpool.domain.ClassPoolDomain;
+import org.jboss.classpool.plugins.DelegatingClassPool;
+import org.jboss.test.classpool.support.MockCachePolicy;
+
+/**
+ * Don't add this test to DelegatingClassPoolTestSuite, it needs a fresh JVM to run properly
+ *
+ * @author <a href="kabir.khan at jboss.com">Kabir Khan</a>
+ * @version $Revision: 1.1 $
+ */
+public class RealCtCacheTestCase extends ClassPoolTest
+{
+ public RealCtCacheTestCase(String name)
+ {
+ super(name);
+ }
+
+ @Override
+ protected void setUp() throws Exception
+ {
+ super.setUp();
+ System.setProperty(CtClassCacheFactory.POLICY_CLASS, MockCachePolicy.class.getName());
+ }
+
+ public void testSimple() throws Exception
+ {
+ MockCachePolicy.policies.clear();
+ ClassPoolDomain parent = createClassPoolDomain("PARENT", null, true);
+ ClassPool pool = createDelegatingClassPool(parent, JAR_A_URL);
+
+ assertEquals(1, MockCachePolicy.policies.size());
+ MockCachePolicy policy = MockCachePolicy.policies.get(0);
+
+ CtClass clazzA1 = pool.get(CLASS_A);
+ assertFalse(policy.wasCached(CLASS_A));
+
+ policy.clearWasCachedClassses();
+ CtClass clazzA2 = pool.get(CLASS_A);
+ assertTrue(policy.wasCached(CLASS_A));
+
+ assertSame(clazzA1, clazzA2);
+ }
+
+ public void testOneDomainLevel() throws Exception
+ {
+ MockCachePolicy.policies.clear();
+ ClassPoolDomain parent = createClassPoolDomain("PARENT", null, true);
+ ClassPool poolA = createDelegatingClassPool(parent, JAR_A_URL);
+
+ assertEquals(1, MockCachePolicy.policies.size());
+ MockCachePolicy policyA = MockCachePolicy.policies.get(0);
+
+ policyA.clearWasCachedClassses();
+ CtClass clazzAa = poolA.get(CLASS_A);
+ assertFalse(policyA.wasCached(CLASS_A));
+ clazzAa = poolA.get(CLASS_A);
+ assertTrue(policyA.wasCached(CLASS_A));
+
+ ClassPool poolB = createDelegatingClassPool(parent, JAR_B_URL);
+
+ assertEquals(2, MockCachePolicy.policies.size());
+ MockCachePolicy policyB = MockCachePolicy.policies.get(1);
+
+ assertNotSame(policyA, policyB);
+
+ //Adding a pool should have removed Class A from pool A's cache
+ policyA.clearWasCachedClassses();
+ policyB.clearWasCachedClassses();
+ clazzAa = poolA.get(CLASS_A);
+ CtClass clazzBa = poolA.get(CLASS_B);
+ CtClass clazzAb = poolB.get(CLASS_A);
+ CtClass clazzBb = poolB.get(CLASS_B);
+ assertSame(clazzAa, clazzAb);
+ assertSame(clazzBa, clazzBb);
+ assertFalse(policyA.wasCached(CLASS_A));
+ assertFalse(policyA.wasCached(CLASS_B));
+ assertFalse(policyB.wasCached(CLASS_A));
+ assertFalse(policyB.wasCached(CLASS_B));
+
+ policyA.clearWasCachedClassses();
+ policyB.clearWasCachedClassses();
+ CtClass clazzAa1 = poolA.get(CLASS_A);
+ CtClass clazzBa1 = poolA.get(CLASS_B);
+ assertSame(clazzAa1, clazzAa);
+ assertSame(clazzBa1, clazzBa);
+ assertTrue(policyA.wasCached(CLASS_A));
+ assertTrue(policyA.wasCached(CLASS_B));
+ assertFalse(policyB.wasCached(CLASS_A));
+ assertFalse(policyB.wasCached(CLASS_B));
+
+ policyA.clearWasCachedClassses();
+ policyB.clearWasCachedClassses();
+ CtClass clazzAb1 = poolB.get(CLASS_A);
+ CtClass clazzBb1 = poolB.get(CLASS_B);
+ assertSame(clazzAb1, clazzAb);
+ assertSame(clazzBb1, clazzBb);
+ assertFalse(policyA.wasCached(CLASS_A));
+ assertFalse(policyA.wasCached(CLASS_B));
+ assertTrue(policyB.wasCached(CLASS_A));
+ assertTrue(policyB.wasCached(CLASS_B));
+
+ clazzAa1 = poolA.get(CLASS_A);
+ clazzBa1 = poolA.get(CLASS_B);
+ assertTrue(policyA.wasCached(CLASS_A));
+ assertTrue(policyA.wasCached(CLASS_B));
+ assertTrue(policyB.wasCached(CLASS_A));
+ assertTrue(policyB.wasCached(CLASS_B));
+
+ //Removing the pool should invalidate pool A's cache
+ ((DelegatingClassPool)poolB).close();
+ MockCachePolicy.policies.remove(1);
+ policyA.clearWasCachedClassses();
+ policyB.clearWasCachedClassses();
+ clazzAa1 = poolA.get(CLASS_A);
+ assertFalse(policyA.wasCached(CLASS_A));
+ }
+
+ public void testParentDelegation() throws Exception
+ {
+ MockCachePolicy.policies.clear();
+ ClassPoolDomain parent = createClassPoolDomain("PARENT", null, true);
+ ClassPool parentA = createDelegatingClassPool(parent, JAR_A_URL);
+
+ assertEquals(1, MockCachePolicy.policies.size());
+ MockCachePolicy.policies.clear();
+
+ ClassPoolDomain child = createClassPoolDomain("CHILD", parent, true);
+ ClassPool childB = createDelegatingClassPool(child, JAR_B_URL);
+
+ assertEquals(1, MockCachePolicy.policies.size());
+ MockCachePolicy childPolicyB = MockCachePolicy.policies.get(0);
+
+ CtClass classA = childB.get(CLASS_A);
+ assertFalse(childPolicyB.wasCached(CLASS_A));
+ childPolicyB.clearWasCachedClassses();
+ CtClass classA1 = childB.get(CLASS_A);
+ assertSame(classA, classA1);
+ assertTrue(childPolicyB.wasCached(CLASS_A));
+
+ //Adding a pool to the parent should invalidate the child cache
+ childPolicyB.clearWasCachedClassses();
+ ClassPool parentB = createDelegatingClassPool(parent, JAR_B_URL);
+ classA1 = childB.get(CLASS_A);
+ assertFalse(childPolicyB.wasCached(CLASS_A));
+ assertSame(classA, classA1);
+ childPolicyB.clearWasCachedClassses();
+ classA1 = childB.get(CLASS_A);
+ assertSame(classA, classA1);
+ assertTrue(childPolicyB.wasCached(CLASS_A));
+
+ //Removing a pool from the parent should invalidate the child cache
+ childPolicyB.clearWasCachedClassses();
+ ((DelegatingClassPool)parentB).close();
+ classA1 = childB.get(CLASS_A);
+ assertFalse(childPolicyB.wasCached(CLASS_A));
+ assertSame(classA, classA1);
+ childPolicyB.clearWasCachedClassses();
+ classA1 = childB.get(CLASS_A);
+ assertSame(classA, classA1);
+ assertTrue(childPolicyB.wasCached(CLASS_A));
+ }
+}
Added: projects/jboss-classpool/trunk/classpool/src/test/java/org/jboss/test/classpool/test/SimpleCtCacheTestCase.java
===================================================================
--- projects/jboss-classpool/trunk/classpool/src/test/java/org/jboss/test/classpool/test/SimpleCtCacheTestCase.java (rev 0)
+++ projects/jboss-classpool/trunk/classpool/src/test/java/org/jboss/test/classpool/test/SimpleCtCacheTestCase.java 2010-01-12 12:53:31 UTC (rev 99279)
@@ -0,0 +1,168 @@
+/*
+* JBoss, Home of Professional Open Source.
+* Copyright 2006, Red Hat Middleware LLC, and individual contributors
+* as indicated by the @author tags. See the copyright.txt file in the
+* distribution for a full listing of individual contributors.
+*
+* This is free software; you can redistribute it and/or modify it
+* under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of
+* the License, or (at your option) any later version.
+*
+* This software is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this software; if not, write to the Free
+* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+package org.jboss.test.classpool.test;
+
+import java.util.Properties;
+
+import javassist.ClassPool;
+import javassist.CtClass;
+
+import org.jboss.classpool.base.CtClassCache;
+import org.jboss.classpool.base.CtClassCacheFactory;
+import org.jboss.util.LRUCachePolicy;
+import org.jboss.util.TimedCachePolicy;
+
+import junit.framework.TestCase;
+
+/**
+ * Don't add this test to DelegatingClassPoolTestSuite, it needs a fresh JVM to run properly
+ *
+ * @author <a href="kabir.khan at jboss.com">Kabir Khan</a>
+ * @version $Revision: 1.1 $
+ */
+public class SimpleCtCacheTestCase extends TestCase
+{
+ public void testDomainCacheFactoryDefaultCacheNoProperties()
+ {
+ CtClassCacheFactory factory = CtClassCacheFactory.createFromProperties();
+ assertEquals(TimedCachePolicy.class, factory.getPolicyClass());
+ assertEquals(CtClassCacheFactory.DEFAULT_TIMED_POLICY_LIFETIME, factory.getLifetime());
+ assertEquals(CtClassCacheFactory.DEFAULT_TIMED_POLICY_RESOLUTION, factory.getResolution());
+ assertEquals(0, factory.getMin());
+ assertEquals(0, factory.getMax());
+ }
+
+ public void testDomainCacheFactoryTimedCacheNoProperties()
+ {
+ Properties properties = new Properties();
+ properties.put(CtClassCacheFactory.POLICY_CLASS, TimedCachePolicy.class.getName());
+ CtClassCacheFactory factory = CtClassCacheFactory.createFromProperties(properties);
+
+ assertEquals(TimedCachePolicy.class, factory.getPolicyClass());
+ assertEquals(CtClassCacheFactory.DEFAULT_TIMED_POLICY_LIFETIME, factory.getLifetime());
+ assertEquals(CtClassCacheFactory.DEFAULT_TIMED_POLICY_RESOLUTION, factory.getResolution());
+ assertEquals(0, factory.getMin());
+ assertEquals(0, factory.getMax());
+ }
+
+ public void testDomainCacheFactoryTimedCacheAndProperties()
+ {
+ Properties properties = new Properties();
+ properties.put(CtClassCacheFactory.POLICY_CLASS, TimedCachePolicy.class.getName());
+ setProperty(properties, CtClassCacheFactory.TIMED_POLICY_LIFETIME, 12);
+ setProperty(properties, CtClassCacheFactory.TIMED_POLICY_RESOLUTION, 23);
+ setProperty(properties, CtClassCacheFactory.LRU_POLICY_MIN, 34);
+ setProperty(properties, CtClassCacheFactory.LRU_POLICY_MAX, 45);
+
+
+ CtClassCacheFactory factory = CtClassCacheFactory.createFromProperties(properties);
+
+ assertEquals(TimedCachePolicy.class, factory.getPolicyClass());
+ assertEquals(12, factory.getLifetime());
+ assertEquals(23, factory.getResolution());
+ assertEquals(0, factory.getMin());
+ assertEquals(0, factory.getMax());
+ }
+
+ public void testDomainCacheFactoryLruCacheNoProperties()
+ {
+ Properties properties = new Properties();
+ properties.put(CtClassCacheFactory.POLICY_CLASS, LRUCachePolicy.class.getName());
+ CtClassCacheFactory factory = CtClassCacheFactory.createFromProperties(properties);
+
+ assertEquals(LRUCachePolicy.class, factory.getPolicyClass());
+ assertEquals(0, factory.getLifetime());
+ assertEquals(0, factory.getResolution());
+ assertEquals(CtClassCacheFactory.DEFAULT_LRU_POLICY_MIN, factory.getMin());
+ assertEquals(CtClassCacheFactory.DEFAULT_LRU_POLICY_MAX, factory.getMax());
+ }
+
+ public void testDomainCacheFactoryLruCacheAndProperties()
+ {
+ Properties properties = new Properties();
+ properties.put(CtClassCacheFactory.POLICY_CLASS, LRUCachePolicy.class.getName());
+ setProperty(properties, CtClassCacheFactory.TIMED_POLICY_LIFETIME, 12);
+ setProperty(properties, CtClassCacheFactory.TIMED_POLICY_RESOLUTION, 23);
+ setProperty(properties, CtClassCacheFactory.LRU_POLICY_MIN, 34);
+ setProperty(properties, CtClassCacheFactory.LRU_POLICY_MAX, 45);
+ CtClassCacheFactory factory = CtClassCacheFactory.createFromProperties(properties);
+
+ assertEquals(LRUCachePolicy.class, factory.getPolicyClass());
+ assertEquals(0, factory.getLifetime());
+ assertEquals(0, factory.getResolution());
+ assertEquals(34, factory.getMin());
+ assertEquals(45, factory.getMax());
+ }
+
+ public void testTimedDomainCache() throws Exception
+ {
+ Properties properties = new Properties();
+ setProperty(properties, CtClassCacheFactory.TIMED_POLICY_LIFETIME, 1);
+ setProperty(properties, CtClassCacheFactory.TIMED_POLICY_RESOLUTION, 1);
+
+ CtClassCacheFactory factory = CtClassCacheFactory.createFromProperties(properties);
+ CtClassCache cache = factory.createCache();
+ assertNotNull(cache);
+
+ ClassPool defPool = ClassPool.getDefault();
+ CtClass clazz = defPool.get(String.class.getName());
+
+ assertNull(cache.get(clazz.getName(), 0));
+ cache.put(clazz.getName(), clazz);
+
+ assertNotNull(cache.get(clazz.getName(), 0));
+
+ Thread.sleep(2000);
+
+ assertNull(cache.get(clazz.getName(), 0));
+
+ cache.put(clazz.getName(), clazz);
+ }
+
+ public void testCacheInvalidation() throws Exception
+ {
+ Properties properties = new Properties();
+ setProperty(properties, CtClassCacheFactory.TIMED_POLICY_LIFETIME, 100);
+ setProperty(properties, CtClassCacheFactory.TIMED_POLICY_RESOLUTION, 10);
+
+ CtClassCacheFactory factory = CtClassCacheFactory.createFromProperties(properties);
+ CtClassCache cache = factory.createCache();
+ assertNotNull(cache);
+
+ ClassPool defPool = ClassPool.getDefault();
+ CtClass clazz = defPool.get(String.class.getName());
+
+ assertNull(cache.get(clazz.getName(), 0));
+ cache.put(clazz.getName(), clazz);
+ assertNotNull(cache.get(clazz.getName(), 0));
+
+ assertNull(cache.get(clazz.getName(), 1));
+ cache.put(clazz.getName(), clazz);
+ assertNotNull(cache.get(clazz.getName(), 1));
+ }
+
+ private void setProperty(Properties properties, String key, int value)
+ {
+ properties.put(key, String.valueOf(value));
+ assertEquals(String.valueOf(value), properties.get(key));
+ }
+}
More information about the jboss-cvs-commits
mailing list