Skip to content

Commit d31312c

Browse files
committed
Try to improve handling of class annotations for AnnotatedClass
1 parent ff441e8 commit d31312c

File tree

2 files changed

+31
-39
lines changed

2 files changed

+31
-39
lines changed

release-notes/VERSION

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ Project: jackson-databind
99
#1317: '@JsonIgnore' annotation not working with creator properties, serialization
1010
#1505: @JsonEnumDefaultValue should take precedence over FAIL_ON_NUMBERS_FOR_ENUMS
1111
(suggested by Stephan S)
12+
- Simplified processing of class annotations (for `AnnotatedClass`) to try to
13+
solve rare concurrency problems with "root name" annotations.
1214

1315
2.8.6 (12-Jan-2017)
1416

src/main/java/com/fasterxml/jackson/databind/introspect/AnnotatedClass.java

Lines changed: 29 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ public final class AnnotatedClass
8888
* Combined list of Jackson annotations that the class has,
8989
* including inheritable ones from super classes and interfaces
9090
*/
91-
protected AnnotationMap _classAnnotations;
91+
final protected AnnotationMap _classAnnotations;
9292

9393
/**
9494
* Flag to indicate whether creator information has been resolved
@@ -144,8 +144,7 @@ public final class AnnotatedClass
144144
*/
145145
private AnnotatedClass(JavaType type, Class<?> rawType, TypeBindings bindings,
146146
List<JavaType> superTypes,
147-
AnnotationIntrospector aintr, MixInResolver mir, TypeFactory tf,
148-
AnnotationMap classAnnotations)
147+
AnnotationIntrospector aintr, MixInResolver mir, TypeFactory tf)
149148
{
150149
_type = type;
151150
_class = rawType;
@@ -156,13 +155,24 @@ private AnnotatedClass(JavaType type, Class<?> rawType, TypeBindings bindings,
156155
_mixInResolver = mir;
157156
_primaryMixIn = (_mixInResolver == null) ? null
158157
: _mixInResolver.findMixInClassFor(_class);
159-
_classAnnotations = classAnnotations;
158+
_classAnnotations = _resolveClassAnnotations();
159+
}
160+
161+
private AnnotatedClass(AnnotatedClass base, AnnotationMap clsAnn) {
162+
_type = base._type;
163+
_class = base._class;
164+
_bindings = base._bindings;
165+
_superTypes = base._superTypes;
166+
_annotationIntrospector = base._annotationIntrospector;
167+
_typeFactory = base._typeFactory;
168+
_mixInResolver = base._mixInResolver;
169+
_primaryMixIn = base._primaryMixIn;
170+
_classAnnotations = clsAnn;
160171
}
161172

162173
@Override
163174
public AnnotatedClass withAnnotations(AnnotationMap ann) {
164-
return new AnnotatedClass(_type, _class, _bindings, _superTypes,
165-
_annotationIntrospector, _mixInResolver, _typeFactory, ann);
175+
return new AnnotatedClass(this, ann);
166176
}
167177

168178
/**
@@ -178,7 +188,7 @@ public static AnnotatedClass construct(JavaType type, MapperConfig<?> config) {
178188
Class<?> raw = type.getRawClass();
179189
return new AnnotatedClass(type, raw, type.getBindings(),
180190
ClassUtil.findSuperTypes(type, null, false), intr,
181-
(MixInResolver) config, config.getTypeFactory(), null);
191+
(MixInResolver) config, config.getTypeFactory());
182192
}
183193

184194
/**
@@ -192,7 +202,7 @@ public static AnnotatedClass construct(JavaType type, MapperConfig<?> config,
192202
Class<?> raw = type.getRawClass();
193203
return new AnnotatedClass(type, raw, type.getBindings(),
194204
ClassUtil.findSuperTypes(type, null, false),
195-
intr, mir, config.getTypeFactory(), null);
205+
intr, mir, config.getTypeFactory());
196206
}
197207

198208
/**
@@ -204,25 +214,25 @@ public static AnnotatedClass constructWithoutSuperTypes(Class<?> cls, MapperConf
204214
{
205215
if (config == null) {
206216
return new AnnotatedClass(null, cls, TypeBindings.emptyBindings(),
207-
Collections.<JavaType>emptyList(), null, null, null, null);
217+
Collections.<JavaType>emptyList(), null, null, null);
208218
}
209219
AnnotationIntrospector intr = config.isAnnotationProcessingEnabled()
210220
? config.getAnnotationIntrospector() : null;
211221
return new AnnotatedClass(null, cls, TypeBindings.emptyBindings(),
212-
Collections.<JavaType>emptyList(), intr, (MixInResolver) config, config.getTypeFactory(), null);
222+
Collections.<JavaType>emptyList(), intr, (MixInResolver) config, config.getTypeFactory());
213223
}
214224

215225
public static AnnotatedClass constructWithoutSuperTypes(Class<?> cls, MapperConfig<?> config,
216226
MixInResolver mir)
217227
{
218228
if (config == null) {
219229
return new AnnotatedClass(null, cls, TypeBindings.emptyBindings(),
220-
Collections.<JavaType>emptyList(), null, null, null, null);
230+
Collections.<JavaType>emptyList(), null, null, null);
221231
}
222232
AnnotationIntrospector intr = config.isAnnotationProcessingEnabled()
223233
? config.getAnnotationIntrospector() : null;
224234
return new AnnotatedClass(null, cls, TypeBindings.emptyBindings(),
225-
Collections.<JavaType>emptyList(), intr, mir, config.getTypeFactory(), null);
235+
Collections.<JavaType>emptyList(), intr, mir, config.getTypeFactory());
226236
}
227237

228238
/*
@@ -253,17 +263,17 @@ public JavaType resolveType(Type type) {
253263

254264
@Override
255265
public <A extends Annotation> A getAnnotation(Class<A> acls) {
256-
return _classAnnotations().get(acls);
266+
return _classAnnotations.get(acls);
257267
}
258268

259269
@Override
260270
public boolean hasAnnotation(Class<?> acls) {
261-
return _classAnnotations().has(acls);
271+
return _classAnnotations.has(acls);
262272
}
263273

264274
@Override
265275
public boolean hasOneOf(Class<? extends Annotation>[] annoClasses) {
266-
return _classAnnotations().hasOneOf(annoClasses);
276+
return _classAnnotations.hasOneOf(annoClasses);
267277
}
268278

269279
@Override
@@ -273,12 +283,12 @@ public Class<?> getRawType() {
273283

274284
@Override
275285
public Iterable<Annotation> annotations() {
276-
return _classAnnotations().annotations();
286+
return _classAnnotations.annotations();
277287
}
278288

279289
@Override
280290
protected AnnotationMap getAllAnnotations() {
281-
return _classAnnotations();
291+
return _classAnnotations;
282292
}
283293

284294
@Override
@@ -293,11 +303,11 @@ public JavaType getType() {
293303
*/
294304

295305
public Annotations getAnnotations() {
296-
return _classAnnotations();
306+
return _classAnnotations;
297307
}
298308

299309
public boolean hasAnnotations() {
300-
return _classAnnotations().size() > 0;
310+
return _classAnnotations.size() > 0;
301311
}
302312

303313
public AnnotatedConstructor getDefaultConstructor()
@@ -381,26 +391,6 @@ public boolean isNonStaticInnerClass()
381391
/**********************************************************
382392
*/
383393

384-
private AnnotationMap _classAnnotations() {
385-
AnnotationMap anns = _classAnnotations;
386-
if (anns == null) {
387-
// 06-Dec-2015, tatu: yes, double-locking, typically not a good choice.
388-
// But for typical usage pattern here (and with JVM 7 and above) is
389-
// a reasonable choice to avoid non-common but existing race condition
390-
// from root name lookup style usage
391-
// Also note that race condition stems from caching only used for loading
392-
// where just class annotations are needed
393-
synchronized (this) {
394-
anns = _classAnnotations;
395-
if (anns == null) {
396-
anns = _resolveClassAnnotations();
397-
_classAnnotations = anns;
398-
}
399-
}
400-
}
401-
return anns;
402-
}
403-
404394
/**
405395
* Initialization method that will recursively collect Jackson
406396
* annotations for this class and all super classes and

0 commit comments

Comments
 (0)