Fixes to javassist.scopepooltags/rel_3_23_0_ga
@@ -16,9 +16,9 @@ | |||
package javassist.scopedpool; | |||
import java.lang.ref.Reference; | |||
import java.lang.ref.WeakReference; | |||
import java.security.ProtectionDomain; | |||
import java.util.Iterator; | |||
import java.util.Map; | |||
import javassist.CannotCompileException; | |||
import javassist.ClassPool; | |||
@@ -37,11 +37,11 @@ import javassist.NotFoundException; | |||
public class ScopedClassPool extends ClassPool { | |||
protected ScopedClassPoolRepository repository; | |||
protected WeakReference classLoader; | |||
protected Reference<ClassLoader> classLoader; | |||
protected LoaderClassPath classPath; | |||
protected SoftValueHashMap softcache = new SoftValueHashMap(); | |||
protected Map<String,CtClass> softcache = new SoftValueHashMap<String,CtClass>(); | |||
boolean isBootstrapCl = true; | |||
@@ -59,10 +59,10 @@ public class ScopedClassPool extends ClassPool { | |||
* the original class pool | |||
* @param repository | |||
* the repository | |||
*@deprecated | |||
*/ | |||
protected ScopedClassPool(ClassLoader cl, ClassPool src, | |||
ScopedClassPoolRepository repository) { | |||
ScopedClassPoolRepository repository) | |||
{ | |||
this(cl, src, repository, false); | |||
} | |||
@@ -78,11 +78,12 @@ public class ScopedClassPool extends ClassPool { | |||
* @param isTemp | |||
* Whether this is a temporary pool used to resolve references | |||
*/ | |||
protected ScopedClassPool(ClassLoader cl, ClassPool src, ScopedClassPoolRepository repository, boolean isTemp) | |||
protected ScopedClassPool(ClassLoader cl, ClassPool src, | |||
ScopedClassPoolRepository repository, boolean isTemp) | |||
{ | |||
super(src); | |||
this.repository = repository; | |||
this.classLoader = new WeakReference(cl); | |||
this.classLoader = new WeakReference<ClassLoader>(cl); | |||
if (cl != null) { | |||
classPath = new LoaderClassPath(cl); | |||
this.insertClassPath(classPath); | |||
@@ -110,7 +111,7 @@ public class ScopedClassPool extends ClassPool { | |||
} | |||
protected ClassLoader getClassLoader0() { | |||
return (ClassLoader)classLoader.get(); | |||
return classLoader.get(); | |||
} | |||
/** | |||
@@ -163,6 +164,7 @@ public class ScopedClassPool extends ClassPool { | |||
* the class name | |||
* @return the class | |||
*/ | |||
@Override | |||
protected CtClass getCached(String classname) { | |||
CtClass clazz = getCachedLocally(classname); | |||
if (clazz == null) { | |||
@@ -186,11 +188,9 @@ public class ScopedClassPool extends ClassPool { | |||
} | |||
if (!isLocal) { | |||
Map registeredCLs = repository.getRegisteredCLs(); | |||
Map<ClassLoader,ScopedClassPool> registeredCLs = repository.getRegisteredCLs(); | |||
synchronized (registeredCLs) { | |||
Iterator it = registeredCLs.values().iterator(); | |||
while (it.hasNext()) { | |||
ScopedClassPool pool = (ScopedClassPool)it.next(); | |||
for (ScopedClassPool pool:registeredCLs.values()) { | |||
if (pool.isUnloadedClassLoader()) { | |||
repository.unregisterClassLoader(pool | |||
.getClassLoader()); | |||
@@ -289,7 +289,7 @@ public class ScopedClassPool extends ClassPool { | |||
* @throws CannotCompileException | |||
* for any error | |||
*/ | |||
public Class toClass(CtClass ct, ClassLoader loader, ProtectionDomain domain) | |||
public Class<?> toClass(CtClass ct, ClassLoader loader, ProtectionDomain domain) | |||
throws CannotCompileException { | |||
// We need to pass up the classloader stored in this pool, as the | |||
// default implementation uses the Thread context cl. |
@@ -81,7 +81,7 @@ public interface ScopedClassPoolRepository { | |||
* | |||
* @return the registered classloaders. | |||
*/ | |||
Map getRegisteredCLs(); | |||
Map<ClassLoader,ScopedClassPool> getRegisteredCLs(); | |||
/** | |||
* This method will check to see if a register classloader has been |
@@ -18,7 +18,7 @@ package javassist.scopedpool; | |||
import java.util.ArrayList; | |||
import java.util.Collections; | |||
import java.util.Iterator; | |||
import java.util.List; | |||
import java.util.Map; | |||
import java.util.WeakHashMap; | |||
@@ -43,8 +43,8 @@ public class ScopedClassPoolRepositoryImpl implements ScopedClassPoolRepository | |||
boolean pruneWhenCached; | |||
/** The registered classloaders */ | |||
protected Map registeredCLs = Collections | |||
.synchronizedMap(new WeakHashMap()); | |||
protected Map<ClassLoader,ScopedClassPool> registeredCLs = Collections | |||
.synchronizedMap(new WeakHashMap<ClassLoader,ScopedClassPool>()); | |||
/** The default class pool */ | |||
protected ClassPool classpool; | |||
@@ -76,6 +76,7 @@ public class ScopedClassPoolRepositoryImpl implements ScopedClassPoolRepository | |||
* | |||
* @return the prune. | |||
*/ | |||
@Override | |||
public boolean isPrune() { | |||
return prune; | |||
} | |||
@@ -85,6 +86,7 @@ public class ScopedClassPoolRepositoryImpl implements ScopedClassPoolRepository | |||
* | |||
* @param prune a new value. | |||
*/ | |||
@Override | |||
public void setPrune(boolean prune) { | |||
this.prune = prune; | |||
} | |||
@@ -96,10 +98,12 @@ public class ScopedClassPoolRepositoryImpl implements ScopedClassPoolRepository | |||
* @param src the original classpool. | |||
* @return the classpool | |||
*/ | |||
@Override | |||
public ScopedClassPool createScopedClassPool(ClassLoader cl, ClassPool src) { | |||
return factory.create(cl, src, this); | |||
} | |||
@Override | |||
public ClassPool findClassPool(ClassLoader cl) { | |||
if (cl == null) | |||
return registerClassLoader(ClassLoader.getSystemClassLoader()); | |||
@@ -113,6 +117,7 @@ public class ScopedClassPoolRepositoryImpl implements ScopedClassPoolRepository | |||
* @param ucl the classloader. | |||
* @return the classpool | |||
*/ | |||
@Override | |||
public ClassPool registerClassLoader(ClassLoader ucl) { | |||
synchronized (registeredCLs) { | |||
// FIXME: Probably want to take this method out later | |||
@@ -121,7 +126,7 @@ public class ScopedClassPoolRepositoryImpl implements ScopedClassPoolRepository | |||
// a | |||
// ClassPool.classpath | |||
if (registeredCLs.containsKey(ucl)) { | |||
return (ClassPool)registeredCLs.get(ucl); | |||
return registeredCLs.get(ucl); | |||
} | |||
ScopedClassPool pool = createScopedClassPool(ucl, classpool); | |||
registeredCLs.put(ucl, pool); | |||
@@ -132,7 +137,8 @@ public class ScopedClassPoolRepositoryImpl implements ScopedClassPoolRepository | |||
/** | |||
* Get the registered classloaders. | |||
*/ | |||
public Map getRegisteredCLs() { | |||
@Override | |||
public Map<ClassLoader,ScopedClassPool> getRegisteredCLs() { | |||
clearUnregisteredClassLoaders(); | |||
return registeredCLs; | |||
} | |||
@@ -141,34 +147,31 @@ public class ScopedClassPoolRepositoryImpl implements ScopedClassPoolRepository | |||
* This method will check to see if a register classloader has been | |||
* undeployed (as in JBoss) | |||
*/ | |||
@Override | |||
public void clearUnregisteredClassLoaders() { | |||
ArrayList toUnregister = null; | |||
List<ClassLoader> toUnregister = null; | |||
synchronized (registeredCLs) { | |||
Iterator it = registeredCLs.values().iterator(); | |||
while (it.hasNext()) { | |||
ScopedClassPool pool = (ScopedClassPool)it.next(); | |||
if (pool.isUnloadedClassLoader()) { | |||
it.remove(); | |||
ClassLoader cl = pool.getClassLoader(); | |||
for (Map.Entry<ClassLoader,ScopedClassPool> reg:registeredCLs.entrySet()) { | |||
if (reg.getValue().isUnloadedClassLoader()) { | |||
ClassLoader cl = reg.getValue().getClassLoader(); | |||
if (cl != null) { | |||
if (toUnregister == null) { | |||
toUnregister = new ArrayList(); | |||
} | |||
if (toUnregister == null) | |||
toUnregister = new ArrayList<ClassLoader>(); | |||
toUnregister.add(cl); | |||
} | |||
registeredCLs.remove(reg.getKey()); | |||
} | |||
} | |||
if (toUnregister != null) { | |||
for (int i = 0; i < toUnregister.size(); i++) { | |||
unregisterClassLoader((ClassLoader)toUnregister.get(i)); | |||
} | |||
} | |||
if (toUnregister != null) | |||
for (ClassLoader cl:toUnregister) | |||
unregisterClassLoader(cl); | |||
} | |||
} | |||
@Override | |||
public void unregisterClassLoader(ClassLoader cl) { | |||
synchronized (registeredCLs) { | |||
ScopedClassPool pool = (ScopedClassPool)registeredCLs.remove(cl); | |||
ScopedClassPool pool = registeredCLs.remove(cl); | |||
if (pool != null) | |||
pool.close(); | |||
} | |||
@@ -178,10 +181,12 @@ public class ScopedClassPoolRepositoryImpl implements ScopedClassPoolRepository | |||
// Noop - this is the end | |||
} | |||
@Override | |||
public void setClassPoolFactory(ScopedClassPoolFactory factory) { | |||
this.factory = factory; | |||
} | |||
@Override | |||
public ScopedClassPoolFactory getClassPoolFactory() { | |||
return factory; | |||
} |
@@ -18,10 +18,14 @@ package javassist.scopedpool; | |||
import java.lang.ref.ReferenceQueue; | |||
import java.lang.ref.SoftReference; | |||
import java.util.AbstractMap; | |||
import java.util.HashMap; | |||
import java.util.AbstractMap.SimpleImmutableEntry; | |||
import java.util.ArrayList; | |||
import java.util.Collection; | |||
import java.util.HashSet; | |||
import java.util.List; | |||
import java.util.Map; | |||
import java.util.Set; | |||
import java.util.concurrent.ConcurrentHashMap; | |||
/** | |||
* This Map will remove entries when the value in the map has been cleaned from | |||
@@ -30,21 +34,21 @@ import java.util.Set; | |||
* @version <tt>$Revision: 1.4 $</tt> | |||
* @author <a href="mailto:bill@jboss.org">Bill Burke</a> | |||
*/ | |||
public class SoftValueHashMap extends AbstractMap implements Map { | |||
private static class SoftValueRef extends SoftReference { | |||
public Object key; | |||
public class SoftValueHashMap<K,V> implements Map<K,V> { | |||
private static class SoftValueRef<K,V> extends SoftReference<V> { | |||
public K key; | |||
private SoftValueRef(Object key, Object val, ReferenceQueue q) { | |||
private SoftValueRef(K key, V val, ReferenceQueue<V> q) { | |||
super(val, q); | |||
this.key = key; | |||
} | |||
private static SoftValueRef create(Object key, Object val, | |||
ReferenceQueue q) { | |||
private static <K,V> SoftValueRef<K,V> create( | |||
K key, V val, ReferenceQueue<V> q) { | |||
if (val == null) | |||
return null; | |||
else | |||
return new SoftValueRef(key, val, q); | |||
return new SoftValueRef<K,V>(key, val, q); | |||
} | |||
} | |||
@@ -52,30 +56,37 @@ public class SoftValueHashMap extends AbstractMap implements Map { | |||
/** | |||
* Returns a set of the mappings contained in this hash table. | |||
*/ | |||
public Set entrySet() { | |||
@Override | |||
public Set<Map.Entry<K, V>> entrySet() { | |||
processQueue(); | |||
return hash.entrySet(); | |||
Set<Entry<K,V>> ret = new HashSet<Entry<K,V>>(); | |||
for (Entry<K,SoftValueRef<K,V>> e:hash.entrySet()) | |||
ret.add(new SimpleImmutableEntry<K,V> ( | |||
e.getKey(), e.getValue().get())); | |||
return ret; | |||
} | |||
/* Hash table mapping WeakKeys to values */ | |||
private Map hash; | |||
private Map<K,SoftValueRef<K,V>> hash; | |||
/* Reference queue for cleared WeakKeys */ | |||
private ReferenceQueue queue = new ReferenceQueue(); | |||
private ReferenceQueue<V> queue = new ReferenceQueue<V>(); | |||
/* | |||
* Remove all invalidated entries from the map, that is, remove all entries | |||
* whose values have been discarded. | |||
*/ | |||
private void processQueue() { | |||
SoftValueRef ref; | |||
while ((ref = (SoftValueRef)queue.poll()) != null) { | |||
if (ref == (SoftValueRef)hash.get(ref.key)) { | |||
// only remove if it is the *exact* same WeakValueRef | |||
// | |||
hash.remove(ref.key); | |||
Object ref; | |||
if (!hash.isEmpty()) | |||
while ((ref = queue.poll()) != null) | |||
if (ref instanceof SoftValueRef) { | |||
@SuppressWarnings("rawtypes") | |||
SoftValueRef que =(SoftValueRef) ref; | |||
if (ref == hash.get(que.key)) | |||
// only remove if it is the *exact* same SoftValueRef | |||
hash.remove(que.key); | |||
} | |||
} | |||
} | |||
/* -- Constructors -- */ | |||
@@ -95,7 +106,7 @@ public class SoftValueHashMap extends AbstractMap implements Map { | |||
* factor is nonpositive | |||
*/ | |||
public SoftValueHashMap(int initialCapacity, float loadFactor) { | |||
hash = new HashMap(initialCapacity, loadFactor); | |||
hash = new ConcurrentHashMap<K,SoftValueRef<K,V>>(initialCapacity, loadFactor); | |||
} | |||
/** | |||
@@ -109,7 +120,7 @@ public class SoftValueHashMap extends AbstractMap implements Map { | |||
* If the initial capacity is less than zero | |||
*/ | |||
public SoftValueHashMap(int initialCapacity) { | |||
hash = new HashMap(initialCapacity); | |||
hash = new ConcurrentHashMap<K,SoftValueRef<K,V>>(initialCapacity); | |||
} | |||
/** | |||
@@ -117,7 +128,7 @@ public class SoftValueHashMap extends AbstractMap implements Map { | |||
* initial capacity and the default load factor, which is <code>0.75</code>. | |||
*/ | |||
public SoftValueHashMap() { | |||
hash = new HashMap(); | |||
hash = new ConcurrentHashMap<K,SoftValueRef<K,V>>(); | |||
} | |||
/** | |||
@@ -129,7 +140,7 @@ public class SoftValueHashMap extends AbstractMap implements Map { | |||
* | |||
* @param t the map whose mappings are to be placed in this map. | |||
*/ | |||
public SoftValueHashMap(Map t) { | |||
public SoftValueHashMap(Map<K,V> t) { | |||
this(Math.max(2 * t.size(), 11), 0.75f); | |||
putAll(t); | |||
} | |||
@@ -142,6 +153,7 @@ public class SoftValueHashMap extends AbstractMap implements Map { | |||
* <code>Map</code> interface, the time required by this operation is | |||
* linear in the size of the map.</em> | |||
*/ | |||
@Override | |||
public int size() { | |||
processQueue(); | |||
return hash.size(); | |||
@@ -150,6 +162,7 @@ public class SoftValueHashMap extends AbstractMap implements Map { | |||
/** | |||
* Returns <code>true</code> if this map contains no key-value mappings. | |||
*/ | |||
@Override | |||
public boolean isEmpty() { | |||
processQueue(); | |||
return hash.isEmpty(); | |||
@@ -162,6 +175,7 @@ public class SoftValueHashMap extends AbstractMap implements Map { | |||
* @param key | |||
* The key whose presence in this map is to be tested. | |||
*/ | |||
@Override | |||
public boolean containsKey(Object key) { | |||
processQueue(); | |||
return hash.containsKey(key); | |||
@@ -177,12 +191,10 @@ public class SoftValueHashMap extends AbstractMap implements Map { | |||
* @param key | |||
* The key whose associated value, if any, is to be returned. | |||
*/ | |||
public Object get(Object key) { | |||
@Override | |||
public V get(Object key) { | |||
processQueue(); | |||
SoftReference ref = (SoftReference)hash.get(key); | |||
if (ref != null) | |||
return ref.get(); | |||
return null; | |||
return valueOrNull(hash.get(key)); | |||
} | |||
/** | |||
@@ -200,12 +212,10 @@ public class SoftValueHashMap extends AbstractMap implements Map { | |||
* @return The previous value to which this key was mapped, or | |||
* <code>null</code> if if there was no mapping for the key | |||
*/ | |||
public Object put(Object key, Object value) { | |||
@Override | |||
public V put(K key, V value) { | |||
processQueue(); | |||
Object rtn = hash.put(key, SoftValueRef.create(key, value, queue)); | |||
if (rtn != null) | |||
rtn = ((SoftReference)rtn).get(); | |||
return rtn; | |||
return valueOrNull(hash.put(key, SoftValueRef.create(key, value, queue))); | |||
} | |||
/** | |||
@@ -218,16 +228,66 @@ public class SoftValueHashMap extends AbstractMap implements Map { | |||
* @return The value to which this key was mapped, or <code>null</code> if | |||
* there was no mapping for the key. | |||
*/ | |||
public Object remove(Object key) { | |||
@Override | |||
public V remove(Object key) { | |||
processQueue(); | |||
return hash.remove(key); | |||
return valueOrNull(hash.remove(key)); | |||
} | |||
/** | |||
* Removes all mappings from this map. | |||
*/ | |||
@Override | |||
public void clear() { | |||
processQueue(); | |||
hash.clear(); | |||
} | |||
/* | |||
* Check whether the supplied value exists. | |||
* @param Object the value to compare. | |||
* @return true if it was found or null. | |||
*/ | |||
@Override | |||
public boolean containsValue(Object arg0) { | |||
processQueue(); | |||
if (null == arg0) | |||
return false; | |||
for (SoftValueRef<K,V> e:hash.values()) | |||
if (null != e && arg0.equals(e.get())) | |||
return true; | |||
return false; | |||
} | |||
/* {@inheritDoc} */ | |||
@Override | |||
public Set<K> keySet() { | |||
processQueue(); | |||
return hash.keySet(); | |||
} | |||
/* {@inheritDoc} */ | |||
@Override | |||
public void putAll(Map<? extends K,? extends V> arg0) { | |||
processQueue(); | |||
for (K key:arg0.keySet()) | |||
put(key, arg0.get(key)); | |||
} | |||
/* {@inheritDoc} */ | |||
@Override | |||
public Collection<V> values() { | |||
processQueue(); | |||
List<V> ret = new ArrayList<V>(); | |||
for (SoftValueRef<K,V> e:hash.values()) | |||
ret.add(e.get()); | |||
return ret; | |||
} | |||
private V valueOrNull(SoftValueRef<K,V> rtn) { | |||
if (null == rtn) | |||
return null; | |||
return rtn.get(); | |||
} | |||
} |
@@ -0,0 +1,242 @@ | |||
/* | |||
* Javassist, a Java-bytecode translator toolkit. | |||
* Copyright (C) 1999- Shigeru Chiba. All Rights Reserved. | |||
* | |||
* The contents of this file are subject to the Mozilla Public License Version | |||
* 1.1 (the "License"); you may not use this file except in compliance with | |||
* the License. Alternatively, the contents of this file may be used under | |||
* the terms of the GNU Lesser General Public License Version 2.1 or later, | |||
* or the Apache License Version 2.0. | |||
* | |||
* Software distributed under the License is distributed on an "AS IS" basis, | |||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License | |||
* for the specific language governing rights and limitations under the | |||
* License. | |||
*/ | |||
package scoped; | |||
import java.io.File; | |||
import java.lang.reflect.Method; | |||
import java.math.BigDecimal; | |||
import java.net.URL; | |||
import java.net.URLClassLoader; | |||
import java.util.Arrays; | |||
import java.util.Map; | |||
import java.util.stream.LongStream; | |||
import javassist.ClassPool; | |||
import javassist.CtClass; | |||
import javassist.CtConstructor; | |||
import javassist.CtField; | |||
import javassist.CtMethod; | |||
import javassist.scopedpool.ScopedClassPool; | |||
import javassist.scopedpool.ScopedClassPoolRepository; | |||
import javassist.scopedpool.ScopedClassPoolRepositoryImpl; | |||
import javassist.scopedpool.SoftValueHashMap; | |||
import junit.framework.TestCase; | |||
/** | |||
* ScopedRepositoryTest. | |||
* | |||
* @author <a href="adrian@jboss.com">Adrian Brock</a> | |||
* @version $Revision$ | |||
*/ | |||
public class ScopedRepositoryTestCase extends TestCase | |||
{ | |||
private static final ScopedClassPoolRepository repository = ScopedClassPoolRepositoryImpl.getInstance(); | |||
public void testJDKClasses() throws Exception | |||
{ | |||
ClassPool poolClass = repository.findClassPool(Class.class.getClassLoader()); | |||
assertNotNull(poolClass); | |||
ClassPool poolString = repository.findClassPool(String.class.getClassLoader()); | |||
assertNotNull(poolString); | |||
assertEquals(poolClass, poolString); | |||
} | |||
public void testScopedClasses() throws Exception | |||
{ | |||
ClassLoader cl = getURLClassLoader("test-classes14-jar1"); | |||
ClassPool pool1 = repository.findClassPool(cl); | |||
CtClass clazz = pool1.get("scoped.jar1.TestClass1"); | |||
assertNotNull(clazz); | |||
ClassPool poolClass = repository.findClassPool(Class.class.getClassLoader()); | |||
assertNotNull(poolClass); | |||
assertNotSame(pool1, poolClass); | |||
} | |||
public void testUnscopedAnnotationUsage() throws Exception | |||
{ | |||
CtClass clazz = getCtClass(UnscopedAnnotationUsage.class); | |||
checkTestAnnotation(clazz, "notDefault"); | |||
} | |||
public void testUnscopedAnnotationDefaultUsage() throws Exception | |||
{ | |||
CtClass clazz = getCtClass(UnscopedAnnotationDefaultUsage.class); | |||
checkTestAnnotation(clazz, "defaultValue"); | |||
} | |||
public void testScopedAnnotationUsage() throws Exception | |||
{ | |||
ClassLoader cl = getURLClassLoader("test-classes14-jar1"); | |||
CtClass clazz = getCtClass("scoped.jar1.ScopedAnnotationUsage", cl); | |||
checkTestAnnotation(clazz, "notDefault"); | |||
} | |||
public void testScopedAnnotationDefaultUsage() throws Exception | |||
{ | |||
ClassLoader cl = getURLClassLoader("test-classes14-jar1"); | |||
CtClass clazz = getCtClass("scoped.jar1.ScopedAnnotationDefaultUsage", cl); | |||
checkTestAnnotation(clazz, "defaultValue"); | |||
} | |||
public void testFullyScopedAnnotationUsage() throws Exception | |||
{ | |||
ClassLoader cl = getURLClassLoader("test-classes14-jar1"); | |||
CtClass clazz = getCtClass("scoped.jar1.FullyScopedAnnotationUsage", cl); | |||
checkScopedAnnotation(cl, clazz, "notDefault"); | |||
} | |||
public void testFullyScopedAnnotationDefaultUsage() throws Exception | |||
{ | |||
ClassLoader cl = getURLClassLoader("test-classes14-jar1"); | |||
CtClass clazz = getCtClass("scoped.jar1.FullyScopedAnnotationDefaultUsage", cl); | |||
checkScopedAnnotation(cl, clazz, "defaultValue"); | |||
} | |||
public void testSoftValueHashMap() throws Exception { | |||
Map<String,Class<?>> map = new SoftValueHashMap<>(); | |||
Class<?> cls = this.getClass(); | |||
assertTrue(map.put(cls.getName(), cls) == null); | |||
assertTrue(map.put(cls.getName(), cls) == cls); | |||
assertTrue(map.size() == 1); | |||
assertTrue(map.get(cls.getName()) == cls); | |||
assertTrue(map.values().iterator().next() == cls); | |||
assertTrue(map.entrySet().iterator().next().getValue() == cls); | |||
assertTrue(map.containsValue(cls)); | |||
assertTrue(map.remove(cls.getName()) == cls); | |||
assertTrue(map.size() == 0); | |||
} | |||
public void testSoftCache() throws Exception { | |||
// Overload the heap to test that the map auto cleans | |||
Map<String,long[]> map = new SoftValueHashMap<>(); | |||
// 12+8*30000000 = +- 252 MB | |||
long[] data = LongStream.range(0, 30000000).toArray(); | |||
int current = map.size(); | |||
while (current <= map.size()) { | |||
current = map.size(); | |||
for (int ii = 0; ii < 5; ii++) { | |||
map.put(current+"-"+ii, Arrays.copyOf(data, data.length)); | |||
} | |||
} | |||
assertTrue(current > map.size()); | |||
} | |||
protected CtClass getCtClass(Class<?> clazz) throws Exception | |||
{ | |||
return getCtClass(clazz.getName(), clazz.getClassLoader()); | |||
} | |||
protected CtClass getCtClass(String name, ClassLoader cl) throws Exception | |||
{ | |||
ClassPool pool = repository.findClassPool(cl); | |||
assertNotNull(pool); | |||
CtClass clazz = pool.get(name); | |||
assertNotNull(clazz); | |||
return clazz; | |||
} | |||
protected void checkTestAnnotation(CtClass ctClass, String value) throws Exception | |||
{ | |||
checkTestAnnotation(ctClass.getAnnotations(), value); | |||
checkTestAnnotation(getFieldAnnotations(ctClass), value); | |||
checkTestAnnotation(getConstructorAnnotations(ctClass), value); | |||
checkTestAnnotation(getConstructorParameterAnnotations(ctClass), value); | |||
checkTestAnnotation(getMethodAnnotations(ctClass), value); | |||
checkTestAnnotation(getMethodParameterAnnotations(ctClass), value); | |||
} | |||
protected void checkTestAnnotation(Object[] annotations, String value) throws Exception | |||
{ | |||
assertNotNull(annotations); | |||
assertEquals(1, annotations.length); | |||
assertNotNull(annotations[0]); | |||
assertTrue(annotations[0] instanceof TestAnnotation); | |||
TestAnnotation annotation = (TestAnnotation) annotations[0]; | |||
assertEquals(value, annotation.something()); | |||
} | |||
protected void checkScopedAnnotation(ClassLoader cl, CtClass ctClass, String value) throws Exception | |||
{ | |||
Class<?> annotationClass = cl.loadClass("scoped.jar1.ScopedTestAnnotation"); | |||
checkScopedAnnotation(annotationClass, ctClass.getAnnotations(), value); | |||
checkScopedAnnotation(annotationClass, getFieldAnnotations(ctClass), value); | |||
checkScopedAnnotation(annotationClass, getConstructorAnnotations(ctClass), value); | |||
checkScopedAnnotation(annotationClass, getConstructorParameterAnnotations(ctClass), value); | |||
checkScopedAnnotation(annotationClass, getMethodAnnotations(ctClass), value); | |||
checkScopedAnnotation(annotationClass, getMethodParameterAnnotations(ctClass), value); | |||
} | |||
protected void checkScopedAnnotation(Class<?> annotationClass, Object[] annotations, String value) throws Exception | |||
{ | |||
assertNotNull(annotations); | |||
assertEquals(1, annotations.length); | |||
assertNotNull(annotations[0]); | |||
assertTrue(annotationClass.isInstance(annotations[0])); | |||
Method method = annotationClass.getMethod("something", new Class<?>[0]); | |||
assertEquals(value, method.invoke(annotations[0], (Object[]) null)); | |||
} | |||
protected Object[] getFieldAnnotations(CtClass clazz) throws Exception | |||
{ | |||
CtField field = clazz.getField("aField"); | |||
assertNotNull(field); | |||
return field.getAnnotations(); | |||
} | |||
protected Object[] getMethodAnnotations(CtClass clazz) throws Exception | |||
{ | |||
CtMethod method = clazz.getMethod("doSomething", "(I)V"); | |||
assertNotNull(method); | |||
return method.getAnnotations(); | |||
} | |||
protected Object[] getMethodParameterAnnotations(CtClass clazz) throws Exception | |||
{ | |||
CtMethod method = clazz.getMethod("doSomething", "(I)V"); | |||
assertNotNull(method); | |||
Object[] paramAnnotations = method.getParameterAnnotations(); | |||
assertNotNull(paramAnnotations); | |||
assertEquals(1, paramAnnotations.length); | |||
return (Object[]) paramAnnotations[0]; | |||
} | |||
protected Object[] getConstructorAnnotations(CtClass clazz) throws Exception | |||
{ | |||
CtConstructor constructor = clazz.getConstructor("(I)V"); | |||
assertNotNull(constructor); | |||
return constructor.getAnnotations(); | |||
} | |||
protected Object[] getConstructorParameterAnnotations(CtClass clazz) throws Exception | |||
{ | |||
CtConstructor constructor = clazz.getConstructor("(I)V"); | |||
assertNotNull(constructor); | |||
Object[] paramAnnotations = constructor.getParameterAnnotations(); | |||
assertNotNull(paramAnnotations); | |||
assertEquals(1, paramAnnotations.length); | |||
return (Object[]) paramAnnotations[0]; | |||
} | |||
protected ClassLoader getURLClassLoader(String context) throws Exception | |||
{ | |||
String output = "."; | |||
File file = new File(output + File.separator + context); | |||
URL url = file.toURI().toURL(); | |||
return new URLClassLoader(new URL[] { url }); | |||
} | |||
} |
@@ -0,0 +1,34 @@ | |||
/* | |||
* Javassist, a Java-bytecode translator toolkit. | |||
* Copyright (C) 1999- Shigeru Chiba. All Rights Reserved. | |||
* | |||
* The contents of this file are subject to the Mozilla Public License Version | |||
* 1.1 (the "License"); you may not use this file except in compliance with | |||
* the License. Alternatively, the contents of this file may be used under | |||
* the terms of the GNU Lesser General Public License Version 2.1 or later, | |||
* or the Apache License Version 2.0. | |||
* | |||
* Software distributed under the License is distributed on an "AS IS" basis, | |||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License | |||
* for the specific language governing rights and limitations under the | |||
* License. | |||
*/ | |||
package scoped; | |||
import java.lang.annotation.ElementType; | |||
import java.lang.annotation.Retention; | |||
import java.lang.annotation.RetentionPolicy; | |||
import java.lang.annotation.Target; | |||
/** | |||
* TestAnnotation. | |||
* | |||
* @author <a href="adrian@jboss.com">Adrian Brock</a> | |||
* @version $Revision$ | |||
*/ | |||
@Retention(value = RetentionPolicy.RUNTIME) | |||
@Target({ ElementType.TYPE, ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.CONSTRUCTOR }) | |||
public @interface TestAnnotation | |||
{ | |||
String something() default "defaultValue"; | |||
} |
@@ -0,0 +1,29 @@ | |||
/* | |||
* Javassist, a Java-bytecode translator toolkit. | |||
* Copyright (C) 1999- Shigeru Chiba. All Rights Reserved. | |||
* | |||
* The contents of this file are subject to the Mozilla Public License Version | |||
* 1.1 (the "License"); you may not use this file except in compliance with | |||
* the License. Alternatively, the contents of this file may be used under | |||
* the terms of the GNU Lesser General Public License Version 2.1 or later, | |||
* or the Apache License Version 2.0. | |||
* | |||
* Software distributed under the License is distributed on an "AS IS" basis, | |||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License | |||
* for the specific language governing rights and limitations under the | |||
* License. | |||
*/ | |||
package scoped; | |||
@TestAnnotation | |||
public class UnscopedAnnotationDefaultUsage | |||
{ | |||
@TestAnnotation | |||
public int aField; | |||
@TestAnnotation | |||
public UnscopedAnnotationDefaultUsage(@TestAnnotation int param) {} | |||
@TestAnnotation | |||
public void doSomething(@TestAnnotation int param) {} | |||
} |
@@ -0,0 +1,29 @@ | |||
/* | |||
* Javassist, a Java-bytecode translator toolkit. | |||
* Copyright (C) 1999- Shigeru Chiba. All Rights Reserved. | |||
* | |||
* The contents of this file are subject to the Mozilla Public License Version | |||
* 1.1 (the "License"); you may not use this file except in compliance with | |||
* the License. Alternatively, the contents of this file may be used under | |||
* the terms of the GNU Lesser General Public License Version 2.1 or later, | |||
* or the Apache License Version 2.0. | |||
* | |||
* Software distributed under the License is distributed on an "AS IS" basis, | |||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License | |||
* for the specific language governing rights and limitations under the | |||
* License. | |||
*/ | |||
package scoped; | |||
@TestAnnotation(something="notDefault") | |||
public class UnscopedAnnotationUsage | |||
{ | |||
@TestAnnotation(something="notDefault") | |||
public int aField; | |||
@TestAnnotation(something="notDefault") | |||
public UnscopedAnnotationUsage(@TestAnnotation(something="notDefault") int param) {} | |||
@TestAnnotation(something="notDefault") | |||
public void doSomething(@TestAnnotation(something="notDefault") int param) {} | |||
} |
@@ -0,0 +1,29 @@ | |||
/* | |||
* Javassist, a Java-bytecode translator toolkit. | |||
* Copyright (C) 1999- Shigeru Chiba. All Rights Reserved. | |||
* | |||
* The contents of this file are subject to the Mozilla Public License Version | |||
* 1.1 (the "License"); you may not use this file except in compliance with | |||
* the License. Alternatively, the contents of this file may be used under | |||
* the terms of the GNU Lesser General Public License Version 2.1 or later, | |||
* or the Apache License Version 2.0. | |||
* | |||
* Software distributed under the License is distributed on an "AS IS" basis, | |||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License | |||
* for the specific language governing rights and limitations under the | |||
* License. | |||
*/ | |||
package scoped.jar1; | |||
@ScopedTestAnnotation | |||
public class FullyScopedAnnotationDefaultUsage | |||
{ | |||
@ScopedTestAnnotation | |||
public int aField; | |||
@ScopedTestAnnotation | |||
public FullyScopedAnnotationDefaultUsage(@ScopedTestAnnotation int value) {} | |||
@ScopedTestAnnotation | |||
public void doSomething(@ScopedTestAnnotation int value) {} | |||
} |
@@ -0,0 +1,29 @@ | |||
/* | |||
* Javassist, a Java-bytecode translator toolkit. | |||
* Copyright (C) 1999- Shigeru Chiba. All Rights Reserved. | |||
* | |||
* The contents of this file are subject to the Mozilla Public License Version | |||
* 1.1 (the "License"); you may not use this file except in compliance with | |||
* the License. Alternatively, the contents of this file may be used under | |||
* the terms of the GNU Lesser General Public License Version 2.1 or later, | |||
* or the Apache License Version 2.0. | |||
* | |||
* Software distributed under the License is distributed on an "AS IS" basis, | |||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License | |||
* for the specific language governing rights and limitations under the | |||
* License. | |||
*/ | |||
package scoped.jar1; | |||
@ScopedTestAnnotation(something="notDefault") | |||
public class FullyScopedAnnotationUsage | |||
{ | |||
@ScopedTestAnnotation(something="notDefault") | |||
public int aField; | |||
@ScopedTestAnnotation(something="notDefault") | |||
public FullyScopedAnnotationUsage(@ScopedTestAnnotation(something="notDefault") int param) {} | |||
@ScopedTestAnnotation(something="notDefault") | |||
public void doSomething(@ScopedTestAnnotation(something="notDefault") int param) {} | |||
} |
@@ -0,0 +1,31 @@ | |||
/* | |||
* Javassist, a Java-bytecode translator toolkit. | |||
* Copyright (C) 1999- Shigeru Chiba. All Rights Reserved. | |||
* | |||
* The contents of this file are subject to the Mozilla Public License Version | |||
* 1.1 (the "License"); you may not use this file except in compliance with | |||
* the License. Alternatively, the contents of this file may be used under | |||
* the terms of the GNU Lesser General Public License Version 2.1 or later, | |||
* or the Apache License Version 2.0. | |||
* | |||
* Software distributed under the License is distributed on an "AS IS" basis, | |||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License | |||
* for the specific language governing rights and limitations under the | |||
* License. | |||
*/ | |||
package scoped.jar1; | |||
import scoped.TestAnnotation; | |||
@TestAnnotation | |||
public class ScopedAnnotationDefaultUsage | |||
{ | |||
@TestAnnotation | |||
public int aField; | |||
@TestAnnotation | |||
public ScopedAnnotationDefaultUsage(@TestAnnotation int param) {} | |||
@TestAnnotation | |||
public void doSomething(@TestAnnotation int param) {} | |||
} |
@@ -0,0 +1,31 @@ | |||
/* | |||
* Javassist, a Java-bytecode translator toolkit. | |||
* Copyright (C) 1999- Shigeru Chiba. All Rights Reserved. | |||
* | |||
* The contents of this file are subject to the Mozilla Public License Version | |||
* 1.1 (the "License"); you may not use this file except in compliance with | |||
* the License. Alternatively, the contents of this file may be used under | |||
* the terms of the GNU Lesser General Public License Version 2.1 or later, | |||
* or the Apache License Version 2.0. | |||
* | |||
* Software distributed under the License is distributed on an "AS IS" basis, | |||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License | |||
* for the specific language governing rights and limitations under the | |||
* License. | |||
*/ | |||
package scoped.jar1; | |||
import scoped.TestAnnotation; | |||
@TestAnnotation(something="notDefault") | |||
public class ScopedAnnotationUsage | |||
{ | |||
@TestAnnotation(something="notDefault") | |||
public int aField; | |||
@TestAnnotation(something="notDefault") | |||
public ScopedAnnotationUsage(@TestAnnotation(something="notDefault") int param) {} | |||
@TestAnnotation(something="notDefault") | |||
public void doSomething(@TestAnnotation(something="notDefault") int param) {} | |||
} |
@@ -0,0 +1,34 @@ | |||
/* | |||
* Javassist, a Java-bytecode translator toolkit. | |||
* Copyright (C) 1999- Shigeru Chiba. All Rights Reserved. | |||
* | |||
* The contents of this file are subject to the Mozilla Public License Version | |||
* 1.1 (the "License"); you may not use this file except in compliance with | |||
* the License. Alternatively, the contents of this file may be used under | |||
* the terms of the GNU Lesser General Public License Version 2.1 or later, | |||
* or the Apache License Version 2.0. | |||
* | |||
* Software distributed under the License is distributed on an "AS IS" basis, | |||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License | |||
* for the specific language governing rights and limitations under the | |||
* License. | |||
*/ | |||
package scoped.jar1; | |||
import java.lang.annotation.ElementType; | |||
import java.lang.annotation.Retention; | |||
import java.lang.annotation.RetentionPolicy; | |||
import java.lang.annotation.Target; | |||
/** | |||
* TestAnnotation. | |||
* | |||
* @author <a href="adrian@jboss.com">Adrian Brock</a> | |||
* @version $Revision$ | |||
*/ | |||
@Retention(value = RetentionPolicy.RUNTIME) | |||
@Target({ ElementType.TYPE, ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.CONSTRUCTOR }) | |||
public @interface ScopedTestAnnotation | |||
{ | |||
String something() default "defaultValue"; | |||
} |
@@ -0,0 +1,26 @@ | |||
/* | |||
* Javassist, a Java-bytecode translator toolkit. | |||
* Copyright (C) 1999- Shigeru Chiba. All Rights Reserved. | |||
* | |||
* The contents of this file are subject to the Mozilla Public License Version | |||
* 1.1 (the "License"); you may not use this file except in compliance with | |||
* the License. Alternatively, the contents of this file may be used under | |||
* the terms of the GNU Lesser General Public License Version 2.1 or later, | |||
* or the Apache License Version 2.0. | |||
* | |||
* Software distributed under the License is distributed on an "AS IS" basis, | |||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License | |||
* for the specific language governing rights and limitations under the | |||
* License. | |||
*/ | |||
package scoped.jar1; | |||
/** | |||
* TestClass1. | |||
* | |||
* @author <a href="adrian@jboss.com">Adrian Brock</a> | |||
* @version $Revision$ | |||
*/ | |||
public class TestClass1 | |||
{ | |||
} |