8068736: Avoid synchronization on Executable/Field.declaredAnnotations
Reviewed-by: jfranck, psandoz
--- a/jdk/src/java.base/share/classes/java/lang/reflect/Executable.java Thu Jan 15 16:45:02 2015 -0800
+++ b/jdk/src/java.base/share/classes/java/lang/reflect/Executable.java Fri Jan 16 12:41:36 2015 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -588,22 +588,29 @@
return AnnotationParser.toArray(declaredAnnotations());
}
- private transient Map<Class<? extends Annotation>, Annotation> declaredAnnotations;
+ private transient volatile Map<Class<? extends Annotation>, Annotation> declaredAnnotations;
- private synchronized Map<Class<? extends Annotation>, Annotation> declaredAnnotations() {
- if (declaredAnnotations == null) {
- Executable root = getRoot();
- if (root != null) {
- declaredAnnotations = root.declaredAnnotations();
- } else {
- declaredAnnotations = AnnotationParser.parseAnnotations(
- getAnnotationBytes(),
- sun.misc.SharedSecrets.getJavaLangAccess().
- getConstantPool(getDeclaringClass()),
- getDeclaringClass());
+ private Map<Class<? extends Annotation>, Annotation> declaredAnnotations() {
+ Map<Class<? extends Annotation>, Annotation> declAnnos;
+ if ((declAnnos = declaredAnnotations) == null) {
+ synchronized (this) {
+ if ((declAnnos = declaredAnnotations) == null) {
+ Executable root = getRoot();
+ if (root != null) {
+ declAnnos = root.declaredAnnotations();
+ } else {
+ declAnnos = AnnotationParser.parseAnnotations(
+ getAnnotationBytes(),
+ sun.misc.SharedSecrets.getJavaLangAccess().
+ getConstantPool(getDeclaringClass()),
+ getDeclaringClass()
+ );
+ }
+ declaredAnnotations = declAnnos;
+ }
}
}
- return declaredAnnotations;
+ return declAnnos;
}
/**
--- a/jdk/src/java.base/share/classes/java/lang/reflect/Field.java Thu Jan 15 16:45:02 2015 -0800
+++ b/jdk/src/java.base/share/classes/java/lang/reflect/Field.java Fri Jan 16 12:41:36 2015 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -1139,21 +1139,28 @@
return AnnotationParser.toArray(declaredAnnotations());
}
- private transient Map<Class<? extends Annotation>, Annotation> declaredAnnotations;
+ private transient volatile Map<Class<? extends Annotation>, Annotation> declaredAnnotations;
- private synchronized Map<Class<? extends Annotation>, Annotation> declaredAnnotations() {
- if (declaredAnnotations == null) {
- Field root = this.root;
- if (root != null) {
- declaredAnnotations = root.declaredAnnotations();
- } else {
- declaredAnnotations = AnnotationParser.parseAnnotations(
- annotations,
- sun.misc.SharedSecrets.getJavaLangAccess().getConstantPool(getDeclaringClass()),
- getDeclaringClass());
+ private Map<Class<? extends Annotation>, Annotation> declaredAnnotations() {
+ Map<Class<? extends Annotation>, Annotation> declAnnos;
+ if ((declAnnos = declaredAnnotations) == null) {
+ synchronized (this) {
+ if ((declAnnos = declaredAnnotations) == null) {
+ Field root = this.root;
+ if (root != null) {
+ declAnnos = root.declaredAnnotations();
+ } else {
+ declAnnos = AnnotationParser.parseAnnotations(
+ annotations,
+ sun.misc.SharedSecrets.getJavaLangAccess()
+ .getConstantPool(getDeclaringClass()),
+ getDeclaringClass());
+ }
+ declaredAnnotations = declAnnos;
+ }
}
}
- return declaredAnnotations;
+ return declAnnos;
}
private native byte[] getTypeAnnotationBytes0();