author | mchung |
Tue, 06 Nov 2018 10:01:16 -0800 | |
changeset 52427 | 3c6aa484536c |
parent 47216 | 71c04702a3d5 |
permissions | -rw-r--r-- |
2 | 1 |
/* |
52427
3c6aa484536c
8211122: Reduce the number of internal classes made accessible to jdk.unsupported
mchung
parents:
47216
diff
changeset
|
2 |
* Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved. |
2 | 3 |
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 |
* |
|
5 |
* This code is free software; you can redistribute it and/or modify it |
|
6 |
* under the terms of the GNU General Public License version 2 only, as |
|
5506 | 7 |
* published by the Free Software Foundation. Oracle designates this |
2 | 8 |
* particular file as subject to the "Classpath" exception as provided |
5506 | 9 |
* by Oracle in the LICENSE file that accompanied this code. |
2 | 10 |
* |
11 |
* This code is distributed in the hope that it will be useful, but WITHOUT |
|
12 |
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
|
13 |
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
|
14 |
* version 2 for more details (a copy is included in the LICENSE file that |
|
15 |
* accompanied this code). |
|
16 |
* |
|
17 |
* You should have received a copy of the GNU General Public License version |
|
18 |
* 2 along with this work; if not, write to the Free Software Foundation, |
|
19 |
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
|
20 |
* |
|
5506 | 21 |
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
22 |
* or visit www.oracle.com if you need additional information or have any |
|
23 |
* questions. |
|
2 | 24 |
*/ |
25 |
||
26 |
package sun.reflect.annotation; |
|
27 |
||
28 |
import java.lang.annotation.*; |
|
29 |
import java.lang.reflect.*; |
|
30 |
import java.util.*; |
|
31 |
import java.security.AccessController; |
|
32 |
import java.security.PrivilegedAction; |
|
52427
3c6aa484536c
8211122: Reduce the number of internal classes made accessible to jdk.unsupported
mchung
parents:
47216
diff
changeset
|
33 |
import jdk.internal.access.SharedSecrets; |
3c6aa484536c
8211122: Reduce the number of internal classes made accessible to jdk.unsupported
mchung
parents:
47216
diff
changeset
|
34 |
import jdk.internal.access.JavaLangAccess; |
2 | 35 |
|
36 |
/** |
|
37 |
* Represents an annotation type at run time. Used to type-check annotations |
|
38 |
* and apply member defaults. |
|
39 |
* |
|
40 |
* @author Josh Bloch |
|
41 |
* @since 1.5 |
|
42 |
*/ |
|
43 |
public class AnnotationType { |
|
44 |
/** |
|
45 |
* Member name -> type mapping. Note that primitive types |
|
46 |
* are represented by the class objects for the corresponding wrapper |
|
47 |
* types. This matches the return value that must be used for a |
|
48 |
* dynamic proxy, allowing for a simple isInstance test. |
|
49 |
*/ |
|
16717
774a7c040e39
7185456: (ann) Optimize Annotation handling in java/sun.reflect.* code for small number of annotations
darcy
parents:
5506
diff
changeset
|
50 |
private final Map<String, Class<?>> memberTypes; |
2 | 51 |
|
52 |
/** |
|
53 |
* Member name -> default value mapping. |
|
54 |
*/ |
|
16717
774a7c040e39
7185456: (ann) Optimize Annotation handling in java/sun.reflect.* code for small number of annotations
darcy
parents:
5506
diff
changeset
|
55 |
private final Map<String, Object> memberDefaults; |
2 | 56 |
|
57 |
/** |
|
28056
0cab6eb92852
8065172: More core reflection final and volatile annotations
martin
parents:
25859
diff
changeset
|
58 |
* Member name -> Method object mapping. This (and its associated |
2 | 59 |
* accessor) are used only to generate AnnotationTypeMismatchExceptions. |
60 |
*/ |
|
16717
774a7c040e39
7185456: (ann) Optimize Annotation handling in java/sun.reflect.* code for small number of annotations
darcy
parents:
5506
diff
changeset
|
61 |
private final Map<String, Method> members; |
2 | 62 |
|
63 |
/** |
|
64 |
* The retention policy for this annotation type. |
|
65 |
*/ |
|
18827
ecbd9c8bef12
7122142: (ann) Race condition between isAnnotationPresent and getAnnotations
plevart
parents:
16717
diff
changeset
|
66 |
private final RetentionPolicy retention; |
2 | 67 |
|
68 |
/** |
|
69 |
* Whether this annotation type is inherited. |
|
70 |
*/ |
|
18827
ecbd9c8bef12
7122142: (ann) Race condition between isAnnotationPresent and getAnnotations
plevart
parents:
16717
diff
changeset
|
71 |
private final boolean inherited; |
2 | 72 |
|
73 |
/** |
|
74 |
* Returns an AnnotationType instance for the specified annotation type. |
|
75 |
* |
|
31061 | 76 |
* @throws IllegalArgumentException if the specified class object |
77 |
* does not represent a valid annotation type |
|
2 | 78 |
*/ |
18827
ecbd9c8bef12
7122142: (ann) Race condition between isAnnotationPresent and getAnnotations
plevart
parents:
16717
diff
changeset
|
79 |
public static AnnotationType getInstance( |
3959
05a07c0a273b
5062288: (reflect) Core reflection uses raw types when it could be using wildcards
darcy
parents:
2
diff
changeset
|
80 |
Class<? extends Annotation> annotationClass) |
2 | 81 |
{ |
32834
e1dca5fe4de3
8137056: Move SharedSecrets and interface friends out of sun.misc
chegar
parents:
32227
diff
changeset
|
82 |
JavaLangAccess jla = SharedSecrets.getJavaLangAccess(); |
18827
ecbd9c8bef12
7122142: (ann) Race condition between isAnnotationPresent and getAnnotations
plevart
parents:
16717
diff
changeset
|
83 |
AnnotationType result = jla.getAnnotationType(annotationClass); // volatile read |
ecbd9c8bef12
7122142: (ann) Race condition between isAnnotationPresent and getAnnotations
plevart
parents:
16717
diff
changeset
|
84 |
if (result == null) { |
ecbd9c8bef12
7122142: (ann) Race condition between isAnnotationPresent and getAnnotations
plevart
parents:
16717
diff
changeset
|
85 |
result = new AnnotationType(annotationClass); |
ecbd9c8bef12
7122142: (ann) Race condition between isAnnotationPresent and getAnnotations
plevart
parents:
16717
diff
changeset
|
86 |
// try to CAS the AnnotationType: null -> result |
ecbd9c8bef12
7122142: (ann) Race condition between isAnnotationPresent and getAnnotations
plevart
parents:
16717
diff
changeset
|
87 |
if (!jla.casAnnotationType(annotationClass, null, result)) { |
ecbd9c8bef12
7122142: (ann) Race condition between isAnnotationPresent and getAnnotations
plevart
parents:
16717
diff
changeset
|
88 |
// somebody was quicker -> read it's result |
ecbd9c8bef12
7122142: (ann) Race condition between isAnnotationPresent and getAnnotations
plevart
parents:
16717
diff
changeset
|
89 |
result = jla.getAnnotationType(annotationClass); |
ecbd9c8bef12
7122142: (ann) Race condition between isAnnotationPresent and getAnnotations
plevart
parents:
16717
diff
changeset
|
90 |
assert result != null; |
ecbd9c8bef12
7122142: (ann) Race condition between isAnnotationPresent and getAnnotations
plevart
parents:
16717
diff
changeset
|
91 |
} |
ecbd9c8bef12
7122142: (ann) Race condition between isAnnotationPresent and getAnnotations
plevart
parents:
16717
diff
changeset
|
92 |
} |
2 | 93 |
|
94 |
return result; |
|
95 |
} |
|
96 |
||
97 |
/** |
|
98 |
* Sole constructor. |
|
99 |
* |
|
100 |
* @param annotationClass the class object for the annotation type |
|
32227
34721a47bc92
8132478: [tidy] three new warnings from java docs (java.net, javax.annotation)
avstepan
parents:
31061
diff
changeset
|
101 |
* @throws IllegalArgumentException if the specified class object for |
34721a47bc92
8132478: [tidy] three new warnings from java docs (java.net, javax.annotation)
avstepan
parents:
31061
diff
changeset
|
102 |
* does not represent a valid annotation type |
2 | 103 |
*/ |
3959
05a07c0a273b
5062288: (reflect) Core reflection uses raw types when it could be using wildcards
darcy
parents:
2
diff
changeset
|
104 |
private AnnotationType(final Class<? extends Annotation> annotationClass) { |
2 | 105 |
if (!annotationClass.isAnnotation()) |
106 |
throw new IllegalArgumentException("Not an annotation type"); |
|
107 |
||
108 |
Method[] methods = |
|
29986
97167d851fc4
8078467: Update core libraries to use diamond with anonymous classes
darcy
parents:
28059
diff
changeset
|
109 |
AccessController.doPrivileged(new PrivilegedAction<>() { |
2 | 110 |
public Method[] run() { |
111 |
// Initialize memberTypes and defaultValues |
|
112 |
return annotationClass.getDeclaredMethods(); |
|
113 |
} |
|
114 |
}); |
|
115 |
||
29986
97167d851fc4
8078467: Update core libraries to use diamond with anonymous classes
darcy
parents:
28059
diff
changeset
|
116 |
memberTypes = new HashMap<>(methods.length+1, 1.0f); |
97167d851fc4
8078467: Update core libraries to use diamond with anonymous classes
darcy
parents:
28059
diff
changeset
|
117 |
memberDefaults = new HashMap<>(0); |
97167d851fc4
8078467: Update core libraries to use diamond with anonymous classes
darcy
parents:
28059
diff
changeset
|
118 |
members = new HashMap<>(methods.length+1, 1.0f); |
2 | 119 |
|
28056
0cab6eb92852
8065172: More core reflection final and volatile annotations
martin
parents:
25859
diff
changeset
|
120 |
for (Method method : methods) { |
38867
84950d65f97a
8147585: Annotations with lambda expressions has parameter result in wrong behavior.
srastogi
parents:
32834
diff
changeset
|
121 |
if (Modifier.isPublic(method.getModifiers()) && |
84950d65f97a
8147585: Annotations with lambda expressions has parameter result in wrong behavior.
srastogi
parents:
32834
diff
changeset
|
122 |
Modifier.isAbstract(method.getModifiers()) && |
84950d65f97a
8147585: Annotations with lambda expressions has parameter result in wrong behavior.
srastogi
parents:
32834
diff
changeset
|
123 |
!method.isSynthetic()) { |
84950d65f97a
8147585: Annotations with lambda expressions has parameter result in wrong behavior.
srastogi
parents:
32834
diff
changeset
|
124 |
if (method.getParameterTypes().length != 0) { |
84950d65f97a
8147585: Annotations with lambda expressions has parameter result in wrong behavior.
srastogi
parents:
32834
diff
changeset
|
125 |
throw new IllegalArgumentException(method + " has params"); |
84950d65f97a
8147585: Annotations with lambda expressions has parameter result in wrong behavior.
srastogi
parents:
32834
diff
changeset
|
126 |
} |
84950d65f97a
8147585: Annotations with lambda expressions has parameter result in wrong behavior.
srastogi
parents:
32834
diff
changeset
|
127 |
String name = method.getName(); |
84950d65f97a
8147585: Annotations with lambda expressions has parameter result in wrong behavior.
srastogi
parents:
32834
diff
changeset
|
128 |
Class<?> type = method.getReturnType(); |
84950d65f97a
8147585: Annotations with lambda expressions has parameter result in wrong behavior.
srastogi
parents:
32834
diff
changeset
|
129 |
memberTypes.put(name, invocationHandlerReturnType(type)); |
84950d65f97a
8147585: Annotations with lambda expressions has parameter result in wrong behavior.
srastogi
parents:
32834
diff
changeset
|
130 |
members.put(name, method); |
2 | 131 |
|
38867
84950d65f97a
8147585: Annotations with lambda expressions has parameter result in wrong behavior.
srastogi
parents:
32834
diff
changeset
|
132 |
Object defaultValue = method.getDefaultValue(); |
84950d65f97a
8147585: Annotations with lambda expressions has parameter result in wrong behavior.
srastogi
parents:
32834
diff
changeset
|
133 |
if (defaultValue != null) { |
84950d65f97a
8147585: Annotations with lambda expressions has parameter result in wrong behavior.
srastogi
parents:
32834
diff
changeset
|
134 |
memberDefaults.put(name, defaultValue); |
84950d65f97a
8147585: Annotations with lambda expressions has parameter result in wrong behavior.
srastogi
parents:
32834
diff
changeset
|
135 |
} |
84950d65f97a
8147585: Annotations with lambda expressions has parameter result in wrong behavior.
srastogi
parents:
32834
diff
changeset
|
136 |
} |
2 | 137 |
} |
138 |
||
139 |
// Initialize retention, & inherited fields. Special treatment |
|
140 |
// of the corresponding annotation types breaks infinite recursion. |
|
141 |
if (annotationClass != Retention.class && |
|
142 |
annotationClass != Inherited.class) { |
|
32834
e1dca5fe4de3
8137056: Move SharedSecrets and interface friends out of sun.misc
chegar
parents:
32227
diff
changeset
|
143 |
JavaLangAccess jla = SharedSecrets.getJavaLangAccess(); |
18827
ecbd9c8bef12
7122142: (ann) Race condition between isAnnotationPresent and getAnnotations
plevart
parents:
16717
diff
changeset
|
144 |
Map<Class<? extends Annotation>, Annotation> metaAnnotations = |
ecbd9c8bef12
7122142: (ann) Race condition between isAnnotationPresent and getAnnotations
plevart
parents:
16717
diff
changeset
|
145 |
AnnotationParser.parseSelectAnnotations( |
ecbd9c8bef12
7122142: (ann) Race condition between isAnnotationPresent and getAnnotations
plevart
parents:
16717
diff
changeset
|
146 |
jla.getRawClassAnnotations(annotationClass), |
ecbd9c8bef12
7122142: (ann) Race condition between isAnnotationPresent and getAnnotations
plevart
parents:
16717
diff
changeset
|
147 |
jla.getConstantPool(annotationClass), |
ecbd9c8bef12
7122142: (ann) Race condition between isAnnotationPresent and getAnnotations
plevart
parents:
16717
diff
changeset
|
148 |
annotationClass, |
ecbd9c8bef12
7122142: (ann) Race condition between isAnnotationPresent and getAnnotations
plevart
parents:
16717
diff
changeset
|
149 |
Retention.class, Inherited.class |
ecbd9c8bef12
7122142: (ann) Race condition between isAnnotationPresent and getAnnotations
plevart
parents:
16717
diff
changeset
|
150 |
); |
ecbd9c8bef12
7122142: (ann) Race condition between isAnnotationPresent and getAnnotations
plevart
parents:
16717
diff
changeset
|
151 |
Retention ret = (Retention) metaAnnotations.get(Retention.class); |
2 | 152 |
retention = (ret == null ? RetentionPolicy.CLASS : ret.value()); |
18827
ecbd9c8bef12
7122142: (ann) Race condition between isAnnotationPresent and getAnnotations
plevart
parents:
16717
diff
changeset
|
153 |
inherited = metaAnnotations.containsKey(Inherited.class); |
ecbd9c8bef12
7122142: (ann) Race condition between isAnnotationPresent and getAnnotations
plevart
parents:
16717
diff
changeset
|
154 |
} |
ecbd9c8bef12
7122142: (ann) Race condition between isAnnotationPresent and getAnnotations
plevart
parents:
16717
diff
changeset
|
155 |
else { |
ecbd9c8bef12
7122142: (ann) Race condition between isAnnotationPresent and getAnnotations
plevart
parents:
16717
diff
changeset
|
156 |
retention = RetentionPolicy.RUNTIME; |
ecbd9c8bef12
7122142: (ann) Race condition between isAnnotationPresent and getAnnotations
plevart
parents:
16717
diff
changeset
|
157 |
inherited = false; |
2 | 158 |
} |
159 |
} |
|
160 |
||
161 |
/** |
|
162 |
* Returns the type that must be returned by the invocation handler |
|
163 |
* of a dynamic proxy in order to have the dynamic proxy return |
|
164 |
* the specified type (which is assumed to be a legal member type |
|
165 |
* for an annotation). |
|
166 |
*/ |
|
3959
05a07c0a273b
5062288: (reflect) Core reflection uses raw types when it could be using wildcards
darcy
parents:
2
diff
changeset
|
167 |
public static Class<?> invocationHandlerReturnType(Class<?> type) { |
2 | 168 |
// Translate primitives to wrappers |
169 |
if (type == byte.class) |
|
170 |
return Byte.class; |
|
171 |
if (type == char.class) |
|
172 |
return Character.class; |
|
173 |
if (type == double.class) |
|
174 |
return Double.class; |
|
175 |
if (type == float.class) |
|
176 |
return Float.class; |
|
177 |
if (type == int.class) |
|
178 |
return Integer.class; |
|
179 |
if (type == long.class) |
|
180 |
return Long.class; |
|
181 |
if (type == short.class) |
|
182 |
return Short.class; |
|
183 |
if (type == boolean.class) |
|
184 |
return Boolean.class; |
|
185 |
||
186 |
// Otherwise, just return declared type |
|
187 |
return type; |
|
188 |
} |
|
189 |
||
190 |
/** |
|
191 |
* Returns member types for this annotation type |
|
31061 | 192 |
* (member name {@literal ->} type mapping). |
2 | 193 |
*/ |
3959
05a07c0a273b
5062288: (reflect) Core reflection uses raw types when it could be using wildcards
darcy
parents:
2
diff
changeset
|
194 |
public Map<String, Class<?>> memberTypes() { |
2 | 195 |
return memberTypes; |
196 |
} |
|
197 |
||
198 |
/** |
|
199 |
* Returns members of this annotation type |
|
31061 | 200 |
* (member name {@literal ->} associated Method object mapping). |
2 | 201 |
*/ |
202 |
public Map<String, Method> members() { |
|
203 |
return members; |
|
204 |
} |
|
205 |
||
206 |
/** |
|
207 |
* Returns the default values for this annotation type |
|
31061 | 208 |
* (Member name {@literal ->} default value mapping). |
2 | 209 |
*/ |
210 |
public Map<String, Object> memberDefaults() { |
|
211 |
return memberDefaults; |
|
212 |
} |
|
213 |
||
214 |
/** |
|
215 |
* Returns the retention policy for this annotation type. |
|
216 |
*/ |
|
217 |
public RetentionPolicy retention() { |
|
218 |
return retention; |
|
219 |
} |
|
220 |
||
221 |
/** |
|
28059
e576535359cc
8067377: My hobby: caning, then then canning, the the can-can
martin
parents:
28056
diff
changeset
|
222 |
* Returns true if this annotation type is inherited. |
2 | 223 |
*/ |
224 |
public boolean isInherited() { |
|
225 |
return inherited; |
|
226 |
} |
|
227 |
||
228 |
/** |
|
229 |
* For debugging. |
|
230 |
*/ |
|
231 |
public String toString() { |
|
18827
ecbd9c8bef12
7122142: (ann) Race condition between isAnnotationPresent and getAnnotations
plevart
parents:
16717
diff
changeset
|
232 |
return "Annotation Type:\n" + |
ecbd9c8bef12
7122142: (ann) Race condition between isAnnotationPresent and getAnnotations
plevart
parents:
16717
diff
changeset
|
233 |
" Member types: " + memberTypes + "\n" + |
ecbd9c8bef12
7122142: (ann) Race condition between isAnnotationPresent and getAnnotations
plevart
parents:
16717
diff
changeset
|
234 |
" Member defaults: " + memberDefaults + "\n" + |
ecbd9c8bef12
7122142: (ann) Race condition between isAnnotationPresent and getAnnotations
plevart
parents:
16717
diff
changeset
|
235 |
" Retention policy: " + retention + "\n" + |
ecbd9c8bef12
7122142: (ann) Race condition between isAnnotationPresent and getAnnotations
plevart
parents:
16717
diff
changeset
|
236 |
" Inherited: " + inherited; |
2 | 237 |
} |
238 |
} |