22 * or visit www.oracle.com if you need additional information or have any |
22 * or visit www.oracle.com if you need additional information or have any |
23 * questions. |
23 * questions. |
24 */ |
24 */ |
25 |
25 |
26 package java.lang.invoke; |
26 package java.lang.invoke; |
|
27 |
|
28 import java.lang.reflect.*; |
|
29 import java.util.*; |
27 import java.lang.invoke.MethodHandleNatives.Constants; |
30 import java.lang.invoke.MethodHandleNatives.Constants; |
|
31 import java.lang.invoke.MethodHandles.Lookup; |
|
32 import static java.lang.invoke.MethodHandleStatics.*; |
28 |
33 |
29 /** |
34 /** |
30 * Cracking (reflecting) method handles back into their constituent symbolic parts. |
35 * A symbolic reference obtained by cracking a method handle into its consitutent symbolic parts. |
31 * |
36 * To crack a direct method handle, call {@link Lookup#revealDirect Lookup.revealDirect}. |
|
37 * <p> |
|
38 * A <em>direct method handle</em> represents a method, constructor, or field without |
|
39 * any intervening argument bindings or other transformations. |
|
40 * The method, constructor, or field referred to by a direct method handle is called |
|
41 * its <em>underlying member</em>. |
|
42 * Direct method handles may be obtained in any of these ways: |
|
43 * <ul> |
|
44 * <li>By executing an {@code ldc} instruction on a {@code CONSTANT_MethodHandle} constant. |
|
45 * (See the Java Virtual Machine Specification, sections 4.4.8 and 5.4.3.) |
|
46 * <li>By calling one of the <a href="MethodHandles.Lookup.html#lookups">Lookup Factory Methods</a>, |
|
47 * such as {@link Lookup#findVirtual Lookup.findVirtual}, |
|
48 * to resolve a symbolic reference into a method handle. |
|
49 * A symbolic reference consists of a class, name string, and type. |
|
50 * <li>By calling the factory method {@link Lookup#unreflect Lookup.unreflect} |
|
51 * or {@link Lookup#unreflectSpecial Lookup.unreflectSpecial} |
|
52 * to convert a {@link Method} into a method handle. |
|
53 * <li>By calling the factory method {@link Lookup#unreflectConstructor Lookup.unreflectConstructor} |
|
54 * to convert a {@link Constructor} into a method handle. |
|
55 * <li>By calling the factory method {@link Lookup#unreflectGetter Lookup.unreflectGetter} |
|
56 * or {@link Lookup#unreflectSetter Lookup.unreflectSetter} |
|
57 * to convert a {@link Field} into a method handle. |
|
58 * </ul> |
|
59 * In all of these cases, it is possible to crack the resulting direct method handle |
|
60 * to recover a symbolic reference for the underlying method, constructor, or field. |
|
61 * Cracking must be done via a {@code Lookup} object equivalent to that which created |
|
62 * the target method handle, or which has enough access permissions to recreate |
|
63 * an equivalent method handle. |
|
64 * |
|
65 * <h1><a name="refkinds"></a>Reference kinds</h1> |
|
66 * The <a href="MethodHandles.Lookup.html#lookups">Lookup Factory Methods</a> |
|
67 * correspond to all major use cases for methods, constructors, and fields. |
|
68 * These use cases may be distinguished using small integers as follows: |
|
69 * <table border=1 cellpadding=5 summary="reference kinds"> |
|
70 * <tr><th>reference kind</th><th>descriptive name</th><th>scope</th><th>member</th><th>behavior</th></tr> |
|
71 * <tr> |
|
72 * <td>{@code 1}</td><td>{@code REF_getField}</td><td>{@code class}</td> |
|
73 * <td>{@code FT f;}</td><td>{@code (T) this.f;}</td> |
|
74 * </tr> |
|
75 * <tr> |
|
76 * <td>{@code 2}</td><td>{@code REF_getStatic}</td><td>{@code class} or {@code interface}</td> |
|
77 * <td>{@code static}<br>{@code FT f;}</td><td>{@code (T) C.f;}</td> |
|
78 * </tr> |
|
79 * <tr> |
|
80 * <td>{@code 3}</td><td>{@code REF_putField}</td><td>{@code class}</td> |
|
81 * <td>{@code FT f;}</td><td>{@code this.f = x;}</td> |
|
82 * </tr> |
|
83 * <tr> |
|
84 * <td>{@code 4}</td><td>{@code REF_putStatic}</td><td>{@code class}</td> |
|
85 * <td>{@code static}<br>{@code FT f;}</td><td>{@code C.f = arg;}</td> |
|
86 * </tr> |
|
87 * <tr> |
|
88 * <td>{@code 5}</td><td>{@code REF_invokeVirtual}</td><td>{@code class}</td> |
|
89 * <td>{@code T m(A*);}</td><td>{@code (T) this.m(arg*);}</td> |
|
90 * </tr> |
|
91 * <tr> |
|
92 * <td>{@code 6}</td><td>{@code REF_invokeStatic}</td><td>{@code class} or {@code interface}</td> |
|
93 * <td>{@code static}<br>{@code T m(A*);}</td><td>{@code (T) C.m(arg*);}</td> |
|
94 * </tr> |
|
95 * <tr> |
|
96 * <td>{@code 7}</td><td>{@code REF_invokeSpecial}</td><td>{@code class} or {@code interface}</td> |
|
97 * <td>{@code T m(A*);}</td><td>{@code (T) super.m(arg*);}</td> |
|
98 * </tr> |
|
99 * <tr> |
|
100 * <td>{@code 8}</td><td>{@code REF_newInvokeSpecial}</td><td>{@code class}</td> |
|
101 * <td>{@code C(A*);}</td><td>{@code new C(arg*);}</td> |
|
102 * </tr> |
|
103 * <tr> |
|
104 * <td>{@code 9}</td><td>{@code REF_invokeInterface}</td><td>{@code interface}</td> |
|
105 * <td>{@code T m(A*);}</td><td>{@code (T) this.m(arg*);}</td> |
|
106 * </tr> |
|
107 * </table> |
|
108 * @since 1.8 |
32 */ |
109 */ |
33 final class MethodHandleInfo { |
110 public |
34 public static final int |
111 interface MethodHandleInfo { |
35 REF_getField = Constants.REF_getField, |
112 /** |
36 REF_getStatic = Constants.REF_getStatic, |
113 * A direct method handle reference kind, |
37 REF_putField = Constants.REF_putField, |
114 * as defined in the <a href="MethodHandleInfo.html#refkinds">table above</a>. |
38 REF_putStatic = Constants.REF_putStatic, |
115 */ |
39 REF_invokeVirtual = Constants.REF_invokeVirtual, |
116 public static final int |
40 REF_invokeStatic = Constants.REF_invokeStatic, |
117 REF_getField = Constants.REF_getField, |
41 REF_invokeSpecial = Constants.REF_invokeSpecial, |
118 REF_getStatic = Constants.REF_getStatic, |
42 REF_newInvokeSpecial = Constants.REF_newInvokeSpecial, |
119 REF_putField = Constants.REF_putField, |
43 REF_invokeInterface = Constants.REF_invokeInterface; |
120 REF_putStatic = Constants.REF_putStatic, |
44 |
121 REF_invokeVirtual = Constants.REF_invokeVirtual, |
45 private final Class<?> declaringClass; |
122 REF_invokeStatic = Constants.REF_invokeStatic, |
46 private final String name; |
123 REF_invokeSpecial = Constants.REF_invokeSpecial, |
47 private final MethodType methodType; |
124 REF_newInvokeSpecial = Constants.REF_newInvokeSpecial, |
48 private final int referenceKind; |
125 REF_invokeInterface = Constants.REF_invokeInterface; |
49 |
126 |
50 public MethodHandleInfo(MethodHandle mh) { |
127 /** |
51 MemberName mn = mh.internalMemberName(); |
128 * Returns the reference kind of the cracked method handle, which in turn |
52 if (mn == null) throw new IllegalArgumentException("not a direct method handle"); |
129 * determines whether the method handle's underlying member was a constructor, method, or field. |
53 this.declaringClass = mn.getDeclaringClass(); |
130 * See the <a href="MethodHandleInfo.html#refkinds">table above</a> for definitions. |
54 this.name = mn.getName(); |
131 * @return the integer code for the kind of reference used to access the underlying member |
55 this.methodType = mn.getMethodOrFieldType(); |
132 */ |
56 byte refKind = mn.getReferenceKind(); |
133 public int getReferenceKind(); |
57 if (refKind == REF_invokeSpecial && !mh.isInvokeSpecial()) |
134 |
58 // Devirtualized method invocation is usually formally virtual. |
135 /** |
59 refKind = REF_invokeVirtual; |
136 * Returns the class in which the cracked method handle's underlying member was defined. |
60 this.referenceKind = refKind; |
137 * @return the declaring class of the underlying member |
61 } |
138 */ |
62 |
139 public Class<?> getDeclaringClass(); |
63 public Class<?> getDeclaringClass() { |
140 |
64 return declaringClass; |
141 /** |
65 } |
142 * Returns the name of the cracked method handle's underlying member. |
66 |
143 * This is {@code "<init>"} if the underlying member was a constructor, |
67 public String getName() { |
144 * else it is a simple method name or field name. |
68 return name; |
145 * @return the simple name of the underlying member |
69 } |
146 */ |
70 |
147 public String getName(); |
71 public MethodType getMethodType() { |
148 |
72 return methodType; |
149 /** |
73 } |
150 * Returns the nominal type of the cracked symbolic reference, expressed as a method type. |
74 |
151 * If the reference is to a constructor, the return type will be {@code void}. |
75 public int getModifiers() { |
152 * If it is to a non-static method, the method type will not mention the {@code this} parameter. |
76 return -1; //TODO |
153 * If it is to a field and the requested access is to read the field, |
77 } |
154 * the method type will have no parameters and return the field type. |
78 |
155 * If it is to a field and the requested access is to write the field, |
79 public int getReferenceKind() { |
156 * the method type will have one parameter of the field type and return {@code void}. |
80 return referenceKind; |
157 * <p> |
81 } |
158 * Note that original direct method handle may include a leading {@code this} parameter, |
82 |
159 * or (in the case of a constructor) will replace the {@code void} return type |
83 static String getReferenceKindString(int referenceKind) { |
160 * with the constructed class. |
84 switch (referenceKind) { |
161 * The nominal type does not include any {@code this} parameter, |
85 case REF_getField: return "getfield"; |
162 * and (in the case of a constructor) will return {@code void}. |
86 case REF_getStatic: return "getstatic"; |
163 * @return the type of the underlying member, expressed as a method type |
87 case REF_putField: return "putfield"; |
164 */ |
88 case REF_putStatic: return "putstatic"; |
165 public MethodType getMethodType(); |
89 case REF_invokeVirtual: return "invokevirtual"; |
166 |
90 case REF_invokeStatic: return "invokestatic"; |
167 // Utility methods. |
91 case REF_invokeSpecial: return "invokespecial"; |
168 // NOTE: class/name/type and reference kind constitute a symbolic reference |
92 case REF_newInvokeSpecial: return "newinvokespecial"; |
169 // member and modifiers are an add-on, derived from Core Reflection (or the equivalent) |
93 case REF_invokeInterface: return "invokeinterface"; |
170 |
94 default: return "UNKNOWN_REFENCE_KIND" + "[" + referenceKind + "]"; |
171 /** |
95 } |
172 * Reflects the underlying member as a method, constructor, or field object. |
|
173 * If the underlying member is public, it is reflected as if by |
|
174 * {@code getMethod}, {@code getConstructor}, or {@code getField}. |
|
175 * Otherwise, it is reflected as if by |
|
176 * {@code getDeclaredMethod}, {@code getDeclaredConstructor}, or {@code getDeclaredField}. |
|
177 * The underlying member must be accessible to the given lookup object. |
|
178 * @param <T> the desired type of the result, either {@link Member} or a subtype |
|
179 * @param expected a class object representing the desired result type {@code T} |
|
180 * @param lookup the lookup object that created this MethodHandleInfo, or one with equivalent access privileges |
|
181 * @return a reference to the method, constructor, or field object |
|
182 * @exception ClassCastException if the member is not of the expected type |
|
183 * @exception NullPointerException if either argument is {@code null} |
|
184 * @exception IllegalArgumentException if the underlying member is not accessible to the given lookup object |
|
185 */ |
|
186 public <T extends Member> T reflectAs(Class<T> expected, Lookup lookup); |
|
187 |
|
188 /** |
|
189 * Returns the access modifiers of the underlying member. |
|
190 * @return the Java language modifiers for underlying member, |
|
191 * or -1 if the member cannot be accessed |
|
192 * @see Modifier |
|
193 * @see reflectAs |
|
194 */ |
|
195 public int getModifiers(); |
|
196 |
|
197 /** |
|
198 * Determines if the underlying member was a variable arity method or constructor. |
|
199 * Such members are represented by method handles that are varargs collectors. |
|
200 * @implSpec |
|
201 * This produces a result equivalent to: |
|
202 * <pre>{@code |
|
203 * getReferenceKind() >= REF_invokeVirtual && Modifier.isTransient(getModifiers()) |
|
204 * }</pre> |
|
205 * |
|
206 * |
|
207 * @return {@code true} if and only if the underlying member was declared with variable arity. |
|
208 */ |
|
209 // spelling derived from java.lang.reflect.Executable, not MethodHandle.isVarargsCollector |
|
210 public default boolean isVarArgs() { |
|
211 // fields are never varargs: |
|
212 if (MethodHandleNatives.refKindIsField((byte) getReferenceKind())) |
|
213 return false; |
|
214 // not in the public API: Modifier.VARARGS |
|
215 final int ACC_VARARGS = 0x00000080; // from JVMS 4.6 (Table 4.20) |
|
216 assert(ACC_VARARGS == Modifier.TRANSIENT); |
|
217 return Modifier.isTransient(getModifiers()); |
96 } |
218 } |
97 |
219 |
98 @Override |
220 /** |
99 public String toString() { |
221 * Returns the descriptive name of the given reference kind, |
100 return String.format("%s %s.%s:%s", getReferenceKindString(referenceKind), |
222 * as defined in the <a href="MethodHandleInfo.html#refkinds">table above</a>. |
101 declaringClass.getName(), name, methodType); |
223 * The conventional prefix "REF_" is omitted. |
|
224 * @param referenceKind an integer code for a kind of reference used to access a class member |
|
225 * @return a mixed-case string such as {@code "getField"} |
|
226 * @exception IllegalArgumentException if the argument is not a valid |
|
227 * <a href="MethodHandleInfo.html#refkinds">reference kind number</a> |
|
228 */ |
|
229 public static String referenceKindToString(int referenceKind) { |
|
230 if (!MethodHandleNatives.refKindIsValid(referenceKind)) |
|
231 throw newIllegalArgumentException("invalid reference kind", referenceKind); |
|
232 return MethodHandleNatives.refKindName((byte)referenceKind); |
|
233 } |
|
234 |
|
235 /** |
|
236 * Returns a string representation for a {@code MethodHandleInfo}, |
|
237 * given the four parts of its symbolic reference. |
|
238 * This is defined to be of the form {@code "RK C.N:MT"}, where {@code RK} is the |
|
239 * {@linkplain #referenceKindToString reference kind string} for {@code kind}, |
|
240 * {@code C} is the {@linkplain java.lang.Class#getName name} of {@code defc} |
|
241 * {@code N} is the {@code name}, and |
|
242 * {@code MT} is the {@code type}. |
|
243 * These four values may be obtained from the |
|
244 * {@linkplain #getReferenceKind reference kind}, |
|
245 * {@linkplain #getDeclaringClass declaring class}, |
|
246 * {@linkplain #getName member name}, |
|
247 * and {@linkplain #getMethodType method type} |
|
248 * of a {@code MethodHandleInfo} object. |
|
249 * |
|
250 * @implSpec |
|
251 * This produces a result equivalent to: |
|
252 * <pre>{@code |
|
253 * String.format("%s %s.%s:%s", referenceKindToString(kind), defc.getName(), name, type) |
|
254 * }</pre> |
|
255 * |
|
256 * @param kind the {@linkplain #getReferenceKind reference kind} part of the symbolic reference |
|
257 * @param defc the {@linkplain #getDeclaringClass declaring class} part of the symbolic reference |
|
258 * @param name the {@linkplain #getName member name} part of the symbolic reference |
|
259 * @param type the {@linkplain #getMethodType method type} part of the symbolic reference |
|
260 * @return a string of the form {@code "RK C.N:MT"} |
|
261 * @exception IllegalArgumentException if the first argument is not a valid |
|
262 * <a href="MethodHandleInfo.html#refkinds">reference kind number</a> |
|
263 * @exception NullPointerException if any reference argument is {@code null} |
|
264 */ |
|
265 public static String toString(int kind, Class<?> defc, String name, MethodType type) { |
|
266 Objects.requireNonNull(name); Objects.requireNonNull(type); |
|
267 return String.format("%s %s.%s:%s", referenceKindToString(kind), defc.getName(), name, type); |
102 } |
268 } |
103 } |
269 } |