Author: markt
Date: Wed Oct 19 09:31:30 2011
New Revision: 1186050

URL: http://svn.apache.org/viewvc?rev=1186050&view=rev
Log:
Correct additional threading and premature clearance issues with the annotation 
cache.

Modified:
    tomcat/tc7.0.x/trunk/   (props changed)
    
tomcat/tc7.0.x/trunk/java/org/apache/catalina/core/DefaultInstanceManager.java
    tomcat/tc7.0.x/trunk/webapps/docs/changelog.xml

Propchange: tomcat/tc7.0.x/trunk/
------------------------------------------------------------------------------
--- svn:mergeinfo (original)
+++ svn:mergeinfo Wed Oct 19 09:31:30 2011
@@ -1 +1 @@
-/tomcat/trunk:1156115,1156171,1156276,1156304,1156519,1156530,1156602,1157015,1157018,1157151,1157198,1157204,1157810,1157832,1157834,1157847,1157908,1157939,1158155,1158160,1158176,1158195,1158198-1158199,1158227,1158331,1158334-1158335,1158426,1160347,1160592,1160611,1160619,1160626,1160639,1160652,1160720-1160721,1160772,1160774,1160776,1161303,1161310,1161322,1161339,1161486,1161540,1161549,1161584,1162082,1162149,1162169,1162721,1162769,1162836,1162932,1163630,1164419,1164438,1164469,1164480,1164567,1165234,1165247-1165248,1165253,1165273,1165282,1165309,1165331,1165338,1165347,1165360-1165361,1165367-1165368,1165602,1165608,1165677,1165693,1165721,1165723,1165728,1165730,1165738,1165746,1165765,1165777,1165918,1165921,1166077,1166150-1166151,1166290,1166366,1166620,1166686,1166752,1166757,1167368,1167394,1169447,1170647,1171692,1172233-1172234,1172236,1172269,1172278,1172282,1172610,1172664,1172689,1172711,1173020-1173021,1173082,1173088,1173090,1173096,1173241,1173256
 
,1173288,1173333,1173342,1173461,1173614,1173630,1173659,1173722,1174061,1174239,1174322,1174325,1174329-1174330,1174337-1174339,1174343,1174353,1174799,1174882,1174884,1174983,1175155,1175158,1175167,1175182,1175190,1175201,1175272,1175275,1175283,1175582,1175589-1175590,1175594,1175602,1175613,1175633,1175690,1175713,1175889,1175896,1175907,1176584,1176590,1176799,1177050,1177060,1177125,1177152,1177160,1177245,1177850,1177862,1177978,1178209,1178228,1178233,1178449,1178542,1178681,1178721,1180261,1180907,1181028,1181123,1181125,1181136,1181291,1181743,1182796,1183078,1183105,1183142,1183328,1183339-1183340,1183492-1183494,1183605,1184917,1184919,1185018,1185020,1185200,1185588,1185626,1186042
+/tomcat/trunk:1156115,1156171,1156276,1156304,1156519,1156530,1156602,1157015,1157018,1157151,1157198,1157204,1157810,1157832,1157834,1157847,1157908,1157939,1158155,1158160,1158176,1158195,1158198-1158199,1158227,1158331,1158334-1158335,1158426,1160347,1160592,1160611,1160619,1160626,1160639,1160652,1160720-1160721,1160772,1160774,1160776,1161303,1161310,1161322,1161339,1161486,1161540,1161549,1161584,1162082,1162149,1162169,1162721,1162769,1162836,1162932,1163630,1164419,1164438,1164469,1164480,1164567,1165234,1165247-1165248,1165253,1165273,1165282,1165309,1165331,1165338,1165347,1165360-1165361,1165367-1165368,1165602,1165608,1165677,1165693,1165721,1165723,1165728,1165730,1165738,1165746,1165765,1165777,1165918,1165921,1166077,1166150-1166151,1166290,1166366,1166620,1166686,1166752,1166757,1167368,1167394,1169447,1170647,1171692,1172233-1172234,1172236,1172269,1172278,1172282,1172556,1172610,1172664,1172689,1172711,1173020-1173021,1173082,1173088,1173090,1173096,1173241
 
,1173256,1173288,1173333,1173342,1173461,1173614,1173630,1173659,1173722,1174061,1174239,1174322,1174325,1174329-1174330,1174337-1174339,1174343,1174353,1174799,1174882,1174884,1174983,1175155,1175158,1175167,1175182,1175190,1175201,1175272,1175275,1175283,1175582,1175589-1175590,1175594,1175602,1175613,1175633,1175690,1175713,1175889,1175896,1175907,1176584,1176590,1176799,1177050,1177060,1177125,1177152,1177160,1177245,1177850,1177862,1177978,1178209,1178228,1178233,1178449,1178542,1178681,1178721,1180261,1180907,1181028,1181123,1181125,1181136,1181291,1181743,1182796,1183078,1183105,1183142,1183328,1183339-1183340,1183492-1183494,1183605,1184917,1184919,1185018,1185020,1185200,1185588,1185626,1186042-1186045

Modified: 
tomcat/tc7.0.x/trunk/java/org/apache/catalina/core/DefaultInstanceManager.java
URL: 
http://svn.apache.org/viewvc/tomcat/tc7.0.x/trunk/java/org/apache/catalina/core/DefaultInstanceManager.java?rev=1186050&r1=1186049&r2=1186050&view=diff
==============================================================================
--- 
tomcat/tc7.0.x/trunk/java/org/apache/catalina/core/DefaultInstanceManager.java 
(original)
+++ 
tomcat/tc7.0.x/trunk/java/org/apache/catalina/core/DefaultInstanceManager.java 
Wed Oct 19 09:31:30 2011
@@ -21,8 +21,6 @@ package org.apache.catalina.core;
 
 import java.io.IOException;
 import java.io.InputStream;
-import java.lang.ref.WeakReference;
-import java.lang.reflect.AccessibleObject;
 import java.lang.reflect.Field;
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
@@ -71,8 +69,8 @@ public class DefaultInstanceManager impl
     private Properties restrictedFilters = new Properties();
     private Properties restrictedListeners = new Properties();
     private Properties restrictedServlets = new Properties();
-    private final Map<Class<?>,WeakReference<List<AnnotationCacheEntry>>> 
annotationCache =
-        new WeakHashMap<Class<?>, WeakReference<List<AnnotationCacheEntry>>>();
+    private final Map<Class<?>,List<AnnotationCacheEntry>> annotationCache =
+        new WeakHashMap<Class<?>, List<AnnotationCacheEntry>>();
 
     public DefaultInstanceManager(Context context, Map<String, Map<String, 
String>> injectionMap, org.apache.catalina.Context catalinaContext, ClassLoader 
containerClassLoader) {
         classLoader = catalinaContext.getLoader().getClassLoader();
@@ -181,13 +179,13 @@ public class DefaultInstanceManager impl
         // method is invoked
         List<AnnotationCacheEntry> annotations;
         synchronized (annotationCache) {
-            annotations = annotationCache.get(clazz).get();
+            annotations = annotationCache.get(clazz);
         }
         for (AnnotationCacheEntry entry : annotations) {
             if (entry.getType() == AnnotationCacheEntryType.POST_CONSTRUCT) {
-                Method postConstruct = (Method) entry.getAccessibleObject();
-                boolean accessibility = postConstruct.isAccessible();
+                Method postConstruct = getMethod(clazz, entry);
                 synchronized (postConstruct) {
+                    boolean accessibility = postConstruct.isAccessible();
                     postConstruct.setAccessible(true);
                     postConstruct.invoke(instance);
                     postConstruct.setAccessible(accessibility);
@@ -217,11 +215,7 @@ public class DefaultInstanceManager impl
         // method is invoked
         List<AnnotationCacheEntry> annotations = null;
         synchronized (annotationCache) {
-            WeakReference<List<AnnotationCacheEntry>> ref =
-                annotationCache.get(clazz);
-            if (ref != null) {
-                annotations = ref.get();
-            }
+            annotations = annotationCache.get(clazz);
         }
         if (annotations == null) {
             // instance not created through the instance manager
@@ -229,9 +223,9 @@ public class DefaultInstanceManager impl
         }
         for (AnnotationCacheEntry entry : annotations) {
             if (entry.getType() == AnnotationCacheEntryType.PRE_DESTROY) {
-                Method preDestroy = (Method) entry.getAccessibleObject();
-                boolean accessibility = preDestroy.isAccessible();
+                Method preDestroy = getMethod(clazz, entry);
                 synchronized (preDestroy) {
+                    boolean accessibility = preDestroy.isAccessible();
                     preDestroy.setAccessible(true);
                     preDestroy.invoke(instance);
                     preDestroy.setAccessible(accessibility);
@@ -257,69 +251,65 @@ public class DefaultInstanceManager impl
             Map<String, String> injections) throws IllegalAccessException,
             InvocationTargetException, NamingException {
 
-        if (context == null) {
-            // No resource injection
-            return;
-        }
-
         while (clazz != null) {
             List<AnnotationCacheEntry> annotations = null;
             synchronized (annotationCache) {
-                WeakReference<List<AnnotationCacheEntry>> ref =
-                    annotationCache.get(clazz);
-                if (ref != null) {
-                    annotations = ref.get();
-                }
+                annotations = annotationCache.get(clazz);
             }
             if (annotations == null) {
                 annotations = new ArrayList<AnnotationCacheEntry>();
-                // Initialize fields annotations
-                Field[] fields = null;
-                if (Globals.IS_SECURITY_ENABLED) {
-                    final Class<?> clazz2 = clazz;
-                    fields = AccessController.doPrivileged(
-                            new PrivilegedAction<Field[]>(){
-                        @Override
-                        public Field[] run(){
-                            return clazz2.getDeclaredFields();
+                
+                if (context != null) {
+                    // Initialize fields annotations for resource injection if
+                    // JNDI is enabled
+                    Field[] fields = null;
+                    if (Globals.IS_SECURITY_ENABLED) {
+                        final Class<?> clazz2 = clazz;
+                        fields = AccessController.doPrivileged(
+                                new PrivilegedAction<Field[]>(){
+                            @Override
+                            public Field[] run(){
+                                return clazz2.getDeclaredFields();
+                            }
+                        });
+                    } else {
+                        fields = clazz.getDeclaredFields();
+                    }
+                    for (Field field : fields) {
+                        if (injections != null && 
injections.containsKey(field.getName())) {
+                            annotations.add(new AnnotationCacheEntry(
+                                    field.getName(), null,
+                                    injections.get(field.getName()),
+                                    AnnotationCacheEntryType.FIELD));
+                        } else if (field.isAnnotationPresent(Resource.class)) {
+                            Resource annotation = 
field.getAnnotation(Resource.class);
+                            annotations.add(new AnnotationCacheEntry(
+                                    field.getName(), null, annotation.name(),
+                                    AnnotationCacheEntryType.FIELD));
+                        } else if (field.isAnnotationPresent(EJB.class)) {
+                            EJB annotation = field.getAnnotation(EJB.class);
+                            annotations.add(new AnnotationCacheEntry(
+                                    field.getName(), null, annotation.name(),
+                                    AnnotationCacheEntryType.FIELD));
+                        } else if 
(field.isAnnotationPresent(WebServiceRef.class)) {
+                            WebServiceRef annotation =
+                                    field.getAnnotation(WebServiceRef.class);
+                            annotations.add(new AnnotationCacheEntry(
+                                    field.getName(), null, annotation.name(),
+                                    AnnotationCacheEntryType.FIELD));
+                        } else if 
(field.isAnnotationPresent(PersistenceContext.class)) {
+                            PersistenceContext annotation =
+                                    
field.getAnnotation(PersistenceContext.class);
+                            annotations.add(new AnnotationCacheEntry(
+                                    field.getName(), null, annotation.name(),
+                                    AnnotationCacheEntryType.FIELD));
+                        } else if 
(field.isAnnotationPresent(PersistenceUnit.class)) {
+                            PersistenceUnit annotation =
+                                    field.getAnnotation(PersistenceUnit.class);
+                            annotations.add(new AnnotationCacheEntry(
+                                    field.getName(), null, annotation.name(),
+                                    AnnotationCacheEntryType.FIELD));
                         }
-                    });
-                } else {
-                    fields = clazz.getDeclaredFields();
-                }
-                for (Field field : fields) {
-                    if (injections != null && 
injections.containsKey(field.getName())) {
-                        annotations.add(new AnnotationCacheEntry(field,
-                                injections.get(field.getName()),
-                                AnnotationCacheEntryType.FIELD));
-                    } else if (field.isAnnotationPresent(Resource.class)) {
-                        Resource annotation = 
field.getAnnotation(Resource.class);
-                        annotations.add(new AnnotationCacheEntry(field,
-                                annotation.name(),
-                                AnnotationCacheEntryType.FIELD));
-                    } else if (field.isAnnotationPresent(EJB.class)) {
-                        EJB annotation = field.getAnnotation(EJB.class);
-                        annotations.add(new AnnotationCacheEntry(field,
-                                annotation.name(),
-                                AnnotationCacheEntryType.FIELD));
-                    } else if (field.isAnnotationPresent(WebServiceRef.class)) 
{
-                        WebServiceRef annotation =
-                                field.getAnnotation(WebServiceRef.class);
-                        annotations.add(new AnnotationCacheEntry(field,
-                                annotation.name(),
-                                AnnotationCacheEntryType.FIELD));
-                    } else if 
(field.isAnnotationPresent(PersistenceContext.class)) {
-                        PersistenceContext annotation =
-                                field.getAnnotation(PersistenceContext.class);
-                        annotations.add(new AnnotationCacheEntry(field,
-                                annotation.name(),
-                                AnnotationCacheEntryType.FIELD));
-                    } else if 
(field.isAnnotationPresent(PersistenceUnit.class)) {
-                        PersistenceUnit annotation =
-                                field.getAnnotation(PersistenceUnit.class);
-                        annotations.add(new AnnotationCacheEntry(field,
-                                annotation.name(),
-                                AnnotationCacheEntryType.FIELD));
                     }
                 }
         
@@ -341,43 +331,58 @@ public class DefaultInstanceManager impl
                 Method preDestroy = null;
                 for (Method method : methods) {
                     String methodName = method.getName();
-                    if (injections != null && methodName.startsWith("set") && 
methodName.length() > 3) {
-                        String fieldName = 
Character.toLowerCase(methodName.charAt(3)) + methodName.substring(4);
-                        if (injections.containsKey(fieldName)) {
-                            annotations.add(new AnnotationCacheEntry(method,
-                                    injections.get(method.getName()),
-                                    AnnotationCacheEntryType.FIELD));
-                            break;
+                    if (context != null) {
+                        // Resource injection only if JNDI is enabled
+                        if (injections != null && methodName.startsWith("set") 
&& methodName.length() > 3) {
+                            String fieldName = 
Character.toLowerCase(methodName.charAt(3)) + methodName.substring(4);
+                            if (injections.containsKey(fieldName)) {
+                                annotations.add(new AnnotationCacheEntry(
+                                        method.getName(),
+                                        method.getParameterTypes(),
+                                        injections.get(method.getName()),
+                                        AnnotationCacheEntryType.SETTER));
+                                break;
+                            }
+                        }
+                        if (method.isAnnotationPresent(Resource.class)) {
+                            Resource annotation = 
method.getAnnotation(Resource.class);
+                            annotations.add(new AnnotationCacheEntry(
+                                    method.getName(),
+                                    method.getParameterTypes(),
+                                    annotation.name(),
+                                    AnnotationCacheEntryType.SETTER));
+                        } else if (method.isAnnotationPresent(EJB.class)) {
+                            EJB annotation = method.getAnnotation(EJB.class);
+                            annotations.add(new AnnotationCacheEntry(
+                                    method.getName(),
+                                    method.getParameterTypes(),
+                                    annotation.name(),
+                                    AnnotationCacheEntryType.SETTER));
+                        } else if 
(method.isAnnotationPresent(WebServiceRef.class)) {
+                            WebServiceRef annotation =
+                                    method.getAnnotation(WebServiceRef.class);
+                            annotations.add(new AnnotationCacheEntry(
+                                    method.getName(),
+                                    method.getParameterTypes(),
+                                    annotation.name(),
+                                    AnnotationCacheEntryType.SETTER));
+                        } else if 
(method.isAnnotationPresent(PersistenceContext.class)) {
+                            PersistenceContext annotation =
+                                    
method.getAnnotation(PersistenceContext.class);
+                            annotations.add(new AnnotationCacheEntry(
+                                    method.getName(),
+                                    method.getParameterTypes(),
+                                    annotation.name(),
+                                    AnnotationCacheEntryType.SETTER));
+                        } else if 
(method.isAnnotationPresent(PersistenceUnit.class)) {
+                            PersistenceUnit annotation =
+                                    
method.getAnnotation(PersistenceUnit.class);
+                            annotations.add(new AnnotationCacheEntry(
+                                    method.getName(),
+                                    method.getParameterTypes(),
+                                    annotation.name(),
+                                    AnnotationCacheEntryType.SETTER));
                         }
-                    }
-                    if (method.isAnnotationPresent(Resource.class)) {
-                        Resource annotation = 
method.getAnnotation(Resource.class);
-                        annotations.add(new AnnotationCacheEntry(method,
-                                annotation.name(),
-                                AnnotationCacheEntryType.FIELD));
-                    } else if (method.isAnnotationPresent(EJB.class)) {
-                        EJB annotation = method.getAnnotation(EJB.class);
-                        annotations.add(new AnnotationCacheEntry(method,
-                                annotation.name(),
-                                AnnotationCacheEntryType.FIELD));
-                    } else if 
(method.isAnnotationPresent(WebServiceRef.class)) {
-                        WebServiceRef annotation =
-                                method.getAnnotation(WebServiceRef.class);
-                        annotations.add(new AnnotationCacheEntry(method,
-                                annotation.name(),
-                                AnnotationCacheEntryType.FIELD));
-                    } else if 
(method.isAnnotationPresent(PersistenceContext.class)) {
-                        PersistenceContext annotation =
-                                method.getAnnotation(PersistenceContext.class);
-                        annotations.add(new AnnotationCacheEntry(method,
-                                annotation.name(),
-                                AnnotationCacheEntryType.FIELD));
-                    } else if 
(method.isAnnotationPresent(PersistenceUnit.class)) {
-                        PersistenceUnit annotation =
-                                method.getAnnotation(PersistenceUnit.class);
-                        annotations.add(new AnnotationCacheEntry(method,
-                                annotation.name(),
-                                AnnotationCacheEntryType.FIELD));
                     }
 
                     if (method.isAnnotationPresent(PostConstruct.class)) {
@@ -405,21 +410,23 @@ public class DefaultInstanceManager impl
                     }
                 }
                 if (postConstruct != null) {
-                    annotations.add(new AnnotationCacheEntry(postConstruct,
-                            null, AnnotationCacheEntryType.POST_CONSTRUCT));
+                    annotations.add(new AnnotationCacheEntry(
+                            postConstruct.getName(),
+                            postConstruct.getParameterTypes(), null,
+                            AnnotationCacheEntryType.POST_CONSTRUCT));
                 }
                 if (preDestroy != null) {
-                    annotations.add(new AnnotationCacheEntry(preDestroy,
-                            null, AnnotationCacheEntryType.PRE_DESTROY));
+                    annotations.add(new AnnotationCacheEntry(
+                            preDestroy.getName(),
+                            preDestroy.getParameterTypes(), null,
+                            AnnotationCacheEntryType.PRE_DESTROY));
                 }
                 if (annotations.size() == 0) {
                     // Use common empty list to save memory 
                     annotations = Collections.emptyList();
                 }
                 synchronized (annotationCache) {
-                    annotationCache.put(clazz,
-                            new WeakReference<List<AnnotationCacheEntry>>(
-                                    annotations));
+                    annotationCache.put(clazz, annotations);
                 }
             }
             clazz = clazz.getSuperclass();
@@ -450,19 +457,17 @@ public class DefaultInstanceManager impl
         while (clazz != null) {
             List<AnnotationCacheEntry> annotations;
             synchronized (annotationCache) {
-                annotations = annotationCache.get(clazz).get();
+                annotations = annotationCache.get(clazz);
             }
             for (AnnotationCacheEntry entry : annotations) {
-                if (entry.getType() == AnnotationCacheEntryType.FIELD) {
-                    if (entry.getAccessibleObject() instanceof Method) {
-                        lookupMethodResource(context, instance,
-                                (Method) entry.getAccessibleObject(),
-                                entry.getName(), clazz);
-                    } else {
-                        lookupFieldResource(context, instance,
-                                (Field) entry.getAccessibleObject(),
-                                entry.getName(), clazz);
-                    }
+                if (entry.getType() == AnnotationCacheEntryType.SETTER) {
+                    lookupMethodResource(context, instance,
+                            getMethod(clazz, entry),
+                            entry.getName(), clazz);
+                } else if (entry.getType() == AnnotationCacheEntryType.FIELD) {
+                    lookupFieldResource(context, instance,
+                            getField(clazz, entry),
+                            entry.getName(), clazz);
                 }
             }
             clazz = clazz.getSuperclass();
@@ -572,8 +577,8 @@ public class DefaultInstanceManager impl
                 context.lookup(clazz.getName() + "/" + field.getName());
         }
 
-        accessibility = field.isAccessible();
         synchronized (field) {
+            accessibility = field.isAccessible();
             field.setAccessible(true);
             field.set(instance, lookedupResource);
             field.setAccessible(accessibility);
@@ -616,8 +621,8 @@ public class DefaultInstanceManager impl
                     clazz.getName() + "/" + getName(method));
         }
 
-        accessibility = method.isAccessible();
         synchronized (method) {
+            accessibility = method.isAccessible();
             method.setAccessible(true);
             method.invoke(instance, lookedupResource);
             method.setAccessible(accessibility);
@@ -643,20 +648,88 @@ public class DefaultInstanceManager impl
         return jndiName;
     }
 
+    private static Method getMethod(final Class<?> clazz,
+            final AnnotationCacheEntry entry) {
+        Method result = null;
+        if (Globals.IS_SECURITY_ENABLED) {
+            result = AccessController.doPrivileged(
+                    new PrivilegedAction<Method>() {
+                        @Override
+                        public Method run() {
+                            Method result = null;
+                            try {
+                                result = clazz.getDeclaredMethod(
+                                        entry.getAccessibleObjectName(),
+                                        entry.getParamTypes());
+                            } catch (NoSuchMethodException e) {
+                                // Should never happen. On that basis don't log
+                                // it.
+                            }
+                            return result;
+                        }
+            });
+        } else {
+            try {
+                result = clazz.getDeclaredMethod(
+                        entry.getAccessibleObjectName(), 
entry.getParamTypes());
+            } catch (NoSuchMethodException e) {
+                // Should never happen. On that basis don't log it.
+            }
+        }
+        return result;
+    }
+
+    private static Field getField(final Class<?> clazz,
+            final AnnotationCacheEntry entry) {
+        Field result = null;
+        if (Globals.IS_SECURITY_ENABLED) {
+            result = AccessController.doPrivileged(
+                    new PrivilegedAction<Field>() {
+                        @Override
+                        public Field run() {
+                            Field result = null;
+                            try {
+                                result = clazz.getDeclaredField(
+                                        entry.getAccessibleObjectName());
+                            } catch (NoSuchFieldException e) {
+                                // Should never happen. On that basis don't log
+                                // it.
+                            }
+                            return result;
+                        }
+            });
+        } else {
+            try {
+                result = clazz.getDeclaredField(
+                        entry.getAccessibleObjectName());
+            } catch (NoSuchFieldException e) {
+                // Should never happen. On that basis don't log it.
+            }
+        }
+        return result;
+    }
+
     private static final class AnnotationCacheEntry {
-        private final AccessibleObject accessibleObject;
+        private final String accessibleObjectName;
+        private final Class<?>[] paramTypes;
         private final String name;
         private final AnnotationCacheEntryType type;
 
-        public AnnotationCacheEntry(AccessibleObject accessibleObject,
-                String name, AnnotationCacheEntryType type) {
-            this.accessibleObject = accessibleObject;
+        public AnnotationCacheEntry(String accessibleObjectName,
+                Class<?>[] paramTypes, String name,
+                AnnotationCacheEntryType type) {
+            this.accessibleObjectName = accessibleObjectName;
+            this.paramTypes = paramTypes;
             this.name = name;
             this.type = type;
         }
 
-        public AccessibleObject getAccessibleObject() {
-            return accessibleObject;
+        public String getAccessibleObjectName() {
+            return accessibleObjectName;
+        }
+
+        public Class<?>[] getParamTypes() {
+            return paramTypes;
         }
 
         public String getName() {
@@ -668,6 +741,6 @@ public class DefaultInstanceManager impl
     }
 
     private static enum AnnotationCacheEntryType {
-        FIELD, POST_CONSTRUCT, PRE_DESTROY
+        FIELD, SETTER, POST_CONSTRUCT, PRE_DESTROY
     }
 }

Modified: tomcat/tc7.0.x/trunk/webapps/docs/changelog.xml
URL: 
http://svn.apache.org/viewvc/tomcat/tc7.0.x/trunk/webapps/docs/changelog.xml?rev=1186050&r1=1186049&r2=1186050&view=diff
==============================================================================
--- tomcat/tc7.0.x/trunk/webapps/docs/changelog.xml (original)
+++ tomcat/tc7.0.x/trunk/webapps/docs/changelog.xml Wed Oct 19 09:31:30 2011
@@ -100,6 +100,10 @@
         could lead to an NPE if multiple threads were processing the same class
         hierarchy for annotations. (markt)
       </fix>
+      <fix>
+        Correct additional threading and premature clearance issues with the
+        annotation cache. (markt)
+      </fix>
     </changelog>
   </subsection>
   <subsection name="Coyote">



---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to