-
Bug
-
Resolution: Fixed
-
P3
-
6
-
b86
-
generic
-
generic
Issue | Fix Version | Assignee | Priority | Status | Resolution | Resolved In Build |
---|---|---|---|---|---|---|
JDK-2137954 | 5.0u8 | Scott Seligman | P2 | Resolved | Fixed | b02 |
java.lang.Class.getAnnotation() is currently implemented with a cache:
public <A extends Annotation> A getAnnotation(Class<A> annotationClass) {
if (annotationClass == null)
throw new NullPointerException();
initAnnotationsIfNecessary();
return (A) annotations.get(annotationClass);
}
<snip>
private synchronized void initAnnotationsIfNecessary() {
if (annotations != null)
return;
declaredAnnotations = AnnotationParser.parseAnnotations(
getRawAnnotations(), getConstantPool(), this);
Class<?> superClass = getSuperclass();
if (superClass == null) {
annotations = declaredAnnotations;
} else {
annotations = new HashMap<Class, Annotation>();
superClass.initAnnotationsIfNecessary();
for (Map.Entry<Class, Annotation> e : superClass.annotations.entrySet()) {
Class annotationClass = e.getKey();
if (AnnotationType.getInstance(annotationClass).isInherited())
annotations.put(annotationClass, e.getValue());
}
annotations.putAll(declaredAnnotations);
}
}
This cache means that getRawAnnotations() is only called once
which doesn't interact well with JVM/TI RedefineClasses(). If
a set of annotations is modified by RedefineClasses(), then
the VM will return the modified annotation (once 5002251 is
fixed), but the Java layer will never present the modified
annotations to the caller.
public <A extends Annotation> A getAnnotation(Class<A> annotationClass) {
if (annotationClass == null)
throw new NullPointerException();
initAnnotationsIfNecessary();
return (A) annotations.get(annotationClass);
}
<snip>
private synchronized void initAnnotationsIfNecessary() {
if (annotations != null)
return;
declaredAnnotations = AnnotationParser.parseAnnotations(
getRawAnnotations(), getConstantPool(), this);
Class<?> superClass = getSuperclass();
if (superClass == null) {
annotations = declaredAnnotations;
} else {
annotations = new HashMap<Class, Annotation>();
superClass.initAnnotationsIfNecessary();
for (Map.Entry<Class, Annotation> e : superClass.annotations.entrySet()) {
Class annotationClass = e.getKey();
if (AnnotationType.getInstance(annotationClass).isInherited())
annotations.put(annotationClass, e.getValue());
}
annotations.putAll(declaredAnnotations);
}
}
This cache means that getRawAnnotations() is only called once
which doesn't interact well with JVM/TI RedefineClasses(). If
a set of annotations is modified by RedefineClasses(), then
the VM will return the modified annotation (once 5002251 is
fixed), but the Java layer will never present the modified
annotations to the caller.
- backported by
-
JDK-2137954 (ann) java.lang.Class.getAnnotation() cache conflicts with RedefineClasses()
- Resolved
- relates to
-
JDK-6422536 (ann) {Constructor,Field,Method}.getAnnotation() cache conflicts with RedefineClasses()
- Open
-
JDK-5002251 potential bug with annotations and class file evolution
- Resolved
-
JDK-6412391 fix for annotation cache and RedefineClasses() conflict needs HotSpot changes
- Resolved
-
JDK-6422541 fix for {Constructor,Field,Method} annotation cache and RedefineClasses() conflict needs HS changes
- Resolved