89 import java.lang.reflect.Constructor; |
89 import java.lang.reflect.Constructor; |
90 import java.lang.reflect.Field; |
90 import java.lang.reflect.Field; |
91 import java.lang.reflect.Method; |
91 import java.lang.reflect.Method; |
92 |
92 |
93 /** |
93 /** |
94 * A wrapper around MethodHandles.Lookup that masks checked exceptions in those cases when you're looking up methods |
94 * A wrapper around {@link java.lang.invoke.MethodHandles.Lookup} that masks |
95 * within your own codebase (therefore it is an error if they are not present). |
95 * checked exceptions. It is useful in those cases when you're looking up |
|
96 * methods within your own codebase (therefore it is an error if they are not |
|
97 * present). |
96 */ |
98 */ |
97 public class Lookup { |
99 public class Lookup { |
98 private final MethodHandles.Lookup lookup; |
100 private final MethodHandles.Lookup lookup; |
99 |
101 |
100 /** |
102 /** |
101 * Creates a new instance, bound to an instance of {@link java.lang.invoke.MethodHandles.Lookup}. |
103 * Creates a new instance, bound to an instance of |
|
104 * {@link java.lang.invoke.MethodHandles.Lookup}. |
102 * |
105 * |
103 * @param lookup the {@link java.lang.invoke.MethodHandles.Lookup} it delegates to. |
106 * @param lookup the {@link java.lang.invoke.MethodHandles.Lookup} it delegates to. |
104 */ |
107 */ |
105 public Lookup(final MethodHandles.Lookup lookup) { |
108 public Lookup(final MethodHandles.Lookup lookup) { |
106 this.lookup = lookup; |
109 this.lookup = lookup; |
110 * A canonical Lookup object that wraps {@link MethodHandles#publicLookup()}. |
113 * A canonical Lookup object that wraps {@link MethodHandles#publicLookup()}. |
111 */ |
114 */ |
112 public static final Lookup PUBLIC = new Lookup(MethodHandles.publicLookup()); |
115 public static final Lookup PUBLIC = new Lookup(MethodHandles.publicLookup()); |
113 |
116 |
114 /** |
117 /** |
115 * Performs a {@link java.lang.invoke.MethodHandles.Lookup#unreflect(Method)}, converting any encountered |
118 * Performs a {@link java.lang.invoke.MethodHandles.Lookup#unreflect(Method)}, |
116 * {@link IllegalAccessException} into an {@link IllegalAccessError}. |
119 * converting any encountered {@link IllegalAccessException} into an |
|
120 * {@link IllegalAccessError}. |
117 * |
121 * |
118 * @param m the method to unreflect |
122 * @param m the method to unreflect |
119 * @return the unreflected method handle. |
123 * @return the unreflected method handle. |
|
124 * @throws IllegalAccessError if the method is inaccessible. |
120 */ |
125 */ |
121 public MethodHandle unreflect(final Method m) { |
126 public MethodHandle unreflect(final Method m) { |
122 return unreflect(lookup, m); |
127 return unreflect(lookup, m); |
123 } |
128 } |
124 |
129 |
125 /** |
130 /** |
126 * Performs a {@link java.lang.invoke.MethodHandles.Lookup#unreflect(Method)}, converting any encountered |
131 * Performs a {@link java.lang.invoke.MethodHandles.Lookup#unreflect(Method)}, |
127 * {@link IllegalAccessException} into an {@link IllegalAccessError}. |
132 * converting any encountered {@link IllegalAccessException} into an |
|
133 * {@link IllegalAccessError}. |
128 * |
134 * |
129 * @param lookup the lookup used to unreflect |
135 * @param lookup the lookup used to unreflect |
130 * @param m the method to unreflect |
136 * @param m the method to unreflect |
131 * @return the unreflected method handle. |
137 * @return the unreflected method handle. |
|
138 * @throws IllegalAccessError if the method is inaccessible. |
132 */ |
139 */ |
133 public static MethodHandle unreflect(final MethodHandles.Lookup lookup, final Method m) { |
140 public static MethodHandle unreflect(final MethodHandles.Lookup lookup, final Method m) { |
134 try { |
141 try { |
135 return lookup.unreflect(m); |
142 return lookup.unreflect(m); |
136 } catch(final IllegalAccessException e) { |
143 } catch(final IllegalAccessException e) { |
139 throw ee; |
146 throw ee; |
140 } |
147 } |
141 } |
148 } |
142 |
149 |
143 /** |
150 /** |
144 * Performs a {@link java.lang.invoke.MethodHandles.Lookup#unreflectGetter(Field)}, converting any encountered |
151 * Performs a {@link java.lang.invoke.MethodHandles.Lookup#unreflectGetter(Field)}, |
145 * {@link IllegalAccessException} into an {@link IllegalAccessError}. |
152 * converting any encountered {@link IllegalAccessException} into an {@link IllegalAccessError}. |
146 * |
153 * |
147 * @param f the field for which a getter is unreflected |
154 * @param f the field for which a getter is unreflected |
148 * @return the unreflected field getter handle. |
155 * @return the unreflected field getter handle. |
|
156 * @throws IllegalAccessError if the getter is inaccessible. |
149 */ |
157 */ |
150 public MethodHandle unreflectGetter(final Field f) { |
158 public MethodHandle unreflectGetter(final Field f) { |
151 try { |
159 try { |
152 return lookup.unreflectGetter(f); |
160 return lookup.unreflectGetter(f); |
153 } catch(final IllegalAccessException e) { |
161 } catch(final IllegalAccessException e) { |
156 throw ee; |
164 throw ee; |
157 } |
165 } |
158 } |
166 } |
159 |
167 |
160 /** |
168 /** |
161 * Performs a {@link java.lang.invoke.MethodHandles.Lookup#findGetter(Class, String, Class)}, converting any |
169 * Performs a {@link java.lang.invoke.MethodHandles.Lookup#findGetter(Class, String, Class)}, |
162 * encountered {@link IllegalAccessException} into an {@link IllegalAccessError} and {@link NoSuchFieldException} |
170 * converting any encountered {@link IllegalAccessException} into an |
163 * into a {@link NoSuchFieldError}. |
171 * {@link IllegalAccessError} and {@link NoSuchFieldException} into a |
|
172 * {@link NoSuchFieldError}. |
164 * |
173 * |
165 * @param refc the class declaring the field |
174 * @param refc the class declaring the field |
166 * @param name the name of the field |
175 * @param name the name of the field |
167 * @param type the type of the field |
176 * @param type the type of the field |
168 * @return the unreflected field getter handle. |
177 * @return the unreflected field getter handle. |
184 throw ee; |
193 throw ee; |
185 } |
194 } |
186 } |
195 } |
187 |
196 |
188 /** |
197 /** |
189 * Performs a {@link java.lang.invoke.MethodHandles.Lookup#unreflectSetter(Field)}, converting any encountered |
198 * Performs a {@link java.lang.invoke.MethodHandles.Lookup#unreflectSetter(Field)}, |
190 * {@link IllegalAccessException} into an {@link IllegalAccessError}. |
199 * converting any encountered {@link IllegalAccessException} into an |
|
200 * {@link IllegalAccessError}. |
191 * |
201 * |
192 * @param f the field for which a setter is unreflected |
202 * @param f the field for which a setter is unreflected |
193 * @return the unreflected field setter handle. |
203 * @return the unreflected field setter handle. |
|
204 * @throws IllegalAccessError if the field is inaccessible. |
|
205 * @throws NoSuchFieldError if the field does not exist. |
194 */ |
206 */ |
195 public MethodHandle unreflectSetter(final Field f) { |
207 public MethodHandle unreflectSetter(final Field f) { |
196 try { |
208 try { |
197 return lookup.unreflectSetter(f); |
209 return lookup.unreflectSetter(f); |
198 } catch(final IllegalAccessException e) { |
210 } catch(final IllegalAccessException e) { |
201 throw ee; |
213 throw ee; |
202 } |
214 } |
203 } |
215 } |
204 |
216 |
205 /** |
217 /** |
206 * Performs a {@link java.lang.invoke.MethodHandles.Lookup#unreflectConstructor(Constructor)}, converting any |
218 * Performs a {@link java.lang.invoke.MethodHandles.Lookup#unreflectConstructor(Constructor)}, |
207 * encountered {@link IllegalAccessException} into an {@link IllegalAccessError}. |
219 * converting any encountered {@link IllegalAccessException} into an |
|
220 * {@link IllegalAccessError}. |
208 * |
221 * |
209 * @param c the constructor to unreflect |
222 * @param c the constructor to unreflect |
210 * @return the unreflected constructor handle. |
223 * @return the unreflected constructor handle. |
|
224 * @throws IllegalAccessError if the constructor is inaccessible. |
211 */ |
225 */ |
212 public MethodHandle unreflectConstructor(final Constructor<?> c) { |
226 public MethodHandle unreflectConstructor(final Constructor<?> c) { |
213 return unreflectConstructor(lookup, c); |
227 return unreflectConstructor(lookup, c); |
214 } |
228 } |
215 |
229 |
216 /** |
230 /** |
217 * Performs a {@link java.lang.invoke.MethodHandles.Lookup#unreflectConstructor(Constructor)}, converting any |
231 * Performs a {@link java.lang.invoke.MethodHandles.Lookup#unreflectConstructor(Constructor)}, |
218 * encountered {@link IllegalAccessException} into an {@link IllegalAccessError}. |
232 * converting any encountered {@link IllegalAccessException} into an |
|
233 * {@link IllegalAccessError}. |
219 * |
234 * |
220 * @param lookup the lookup used to unreflect |
235 * @param lookup the lookup used to unreflect |
221 * @param c the constructor to unreflect |
236 * @param c the constructor to unreflect |
222 * @return the unreflected constructor handle. |
237 * @return the unreflected constructor handle. |
|
238 * @throws IllegalAccessError if the constructor is inaccessible. |
223 */ |
239 */ |
224 public static MethodHandle unreflectConstructor(final MethodHandles.Lookup lookup, final Constructor<?> c) { |
240 public static MethodHandle unreflectConstructor(final MethodHandles.Lookup lookup, final Constructor<?> c) { |
225 try { |
241 try { |
226 return lookup.unreflectConstructor(c); |
242 return lookup.unreflectConstructor(c); |
227 } catch(final IllegalAccessException e) { |
243 } catch(final IllegalAccessException e) { |
230 throw ee; |
246 throw ee; |
231 } |
247 } |
232 } |
248 } |
233 |
249 |
234 /** |
250 /** |
235 * Performs a findSpecial on the underlying lookup. Converts any encountered {@link IllegalAccessException} into an |
251 * Performs a {@link java.lang.invoke.MethodHandles.Lookup#findSpecial(Class, String, MethodType, Class)} |
236 * {@link IllegalAccessError} and a {@link NoSuchMethodException} into a {@link NoSuchMethodError}. |
252 * on the underlying lookup. Converts any encountered |
|
253 * {@link IllegalAccessException} into an {@link IllegalAccessError} and |
|
254 * {@link NoSuchMethodException} into a {@link NoSuchMethodError}. |
237 * |
255 * |
238 * @param declaringClass class declaring the method |
256 * @param declaringClass class declaring the method |
239 * @param name the name of the method |
257 * @param name the name of the method |
240 * @param type the type of the method |
258 * @param type the type of the method |
241 * @return a method handle for the method |
259 * @return a method handle for the method |
261 private static String methodDescription(final Class<?> declaringClass, final String name, final MethodType type) { |
279 private static String methodDescription(final Class<?> declaringClass, final String name, final MethodType type) { |
262 return declaringClass.getName() + "#" + name + type; |
280 return declaringClass.getName() + "#" + name + type; |
263 } |
281 } |
264 |
282 |
265 /** |
283 /** |
266 * Performs a findStatic on the underlying lookup. Converts any encountered {@link IllegalAccessException} into an |
284 * Performs a {@link java.lang.invoke.MethodHandles.Lookup#findStatic(Class, String, MethodType)} |
267 * {@link IllegalAccessError} and a {@link NoSuchMethodException} into a {@link NoSuchMethodError}. |
285 * on the underlying lookup. Converts any encountered |
|
286 * {@link IllegalAccessException} into an {@link IllegalAccessError} and |
|
287 * {@link NoSuchMethodException} into a {@link NoSuchMethodError}. |
268 * |
288 * |
269 * @param declaringClass class declaring the method |
289 * @param declaringClass class declaring the method |
270 * @param name the name of the method |
290 * @param name the name of the method |
271 * @param type the type of the method |
291 * @param type the type of the method |
272 * @return a method handle for the method |
292 * @return a method handle for the method |
288 throw ee; |
308 throw ee; |
289 } |
309 } |
290 } |
310 } |
291 |
311 |
292 /** |
312 /** |
293 * Performs a findVirtual on the underlying lookup. Converts any encountered {@link IllegalAccessException} into an |
313 * Performs a {@link java.lang.invoke.MethodHandles.Lookup#findVirtual(Class, String, MethodType)} |
294 * {@link IllegalAccessError} and a {@link NoSuchMethodException} into a {@link NoSuchMethodError}. |
314 * on the underlying lookup. Converts any encountered |
|
315 * {@link IllegalAccessException} into an {@link IllegalAccessError} and |
|
316 * {@link NoSuchMethodException} into a {@link NoSuchMethodError}. |
295 * |
317 * |
296 * @param declaringClass class declaring the method |
318 * @param declaringClass class declaring the method |
297 * @param name the name of the method |
319 * @param name the name of the method |
298 * @param type the type of the method |
320 * @param type the type of the method |
299 * @return a method handle for the method |
321 * @return a method handle for the method |
315 throw ee; |
337 throw ee; |
316 } |
338 } |
317 } |
339 } |
318 |
340 |
319 /** |
341 /** |
320 * Given a lookup, finds using {@link #findSpecial(Class, String, MethodType)} a method on that lookup's class. |
342 * Given a lookup, finds using {@link #findSpecial(Class, String, MethodType)} |
321 * Useful in classes' code for convenient linking to their own privates. |
343 * a method on that lookup's class. Useful in classes' code for convenient |
|
344 * linking to their own privates. |
322 * @param lookup the lookup for the class |
345 * @param lookup the lookup for the class |
323 * @param name the name of the method |
346 * @param name the name of the method |
324 * @param rtype the return type of the method |
347 * @param rtype the return type of the method |
325 * @param ptypes the parameter types of the method |
348 * @param ptypes the parameter types of the method |
326 * @return the method handle for the method |
349 * @return the method handle for the method |
329 return new Lookup(lookup).findOwnSpecial(name, rtype, ptypes); |
352 return new Lookup(lookup).findOwnSpecial(name, rtype, ptypes); |
330 } |
353 } |
331 |
354 |
332 |
355 |
333 /** |
356 /** |
334 * Finds using {@link #findSpecial(Class, String, MethodType)} a method on that lookup's class. Useful in classes' |
357 * Finds using {@link #findSpecial(Class, String, MethodType)} a method on |
335 * code for convenient linking to their own privates. It's easier to use than {@code findSpecial} in that you can |
358 * that lookup's class. Useful in classes' code for convenient linking to |
336 * just list the parameter types, and don't have to specify lookup class. |
359 * their own privates. It's also more convenient than {@code findSpecial} |
|
360 * in that you can just list the parameter types, and don't have to specify |
|
361 * lookup class. |
337 * @param name the name of the method |
362 * @param name the name of the method |
338 * @param rtype the return type of the method |
363 * @param rtype the return type of the method |
339 * @param ptypes the parameter types of the method |
364 * @param ptypes the parameter types of the method |
340 * @return the method handle for the method |
365 * @return the method handle for the method |
341 */ |
366 */ |
342 public MethodHandle findOwnSpecial(final String name, final Class<?> rtype, final Class<?>... ptypes) { |
367 public MethodHandle findOwnSpecial(final String name, final Class<?> rtype, final Class<?>... ptypes) { |
343 return findSpecial(lookup.lookupClass(), name, MethodType.methodType(rtype, ptypes)); |
368 return findSpecial(lookup.lookupClass(), name, MethodType.methodType(rtype, ptypes)); |
344 } |
369 } |
345 |
370 |
346 /** |
371 /** |
347 * Given a lookup, finds using {@link #findStatic(Class, String, MethodType)} a method on that lookup's class. |
372 * Given a lookup, finds using {@link #findStatic(Class, String, MethodType)} |
348 * Useful in classes' code for convenient linking to their own privates. It's easier to use than {@code findStatic} |
373 * a method on that lookup's class. Useful in classes' code for convenient |
349 * in that you can just list the parameter types, and don't have to specify lookup class. |
374 * linking to their own privates. It's easier to use than {@code findStatic} |
|
375 * in that you can just list the parameter types, and don't have to specify |
|
376 * lookup class. |
350 * @param lookup the lookup for the class |
377 * @param lookup the lookup for the class |
351 * @param name the name of the method |
378 * @param name the name of the method |
352 * @param rtype the return type of the method |
379 * @param rtype the return type of the method |
353 * @param ptypes the parameter types of the method |
380 * @param ptypes the parameter types of the method |
354 * @return the method handle for the method |
381 * @return the method handle for the method |
356 public static MethodHandle findOwnStatic(final MethodHandles.Lookup lookup, final String name, final Class<?> rtype, final Class<?>... ptypes) { |
383 public static MethodHandle findOwnStatic(final MethodHandles.Lookup lookup, final String name, final Class<?> rtype, final Class<?>... ptypes) { |
357 return new Lookup(lookup).findOwnStatic(name, rtype, ptypes); |
384 return new Lookup(lookup).findOwnStatic(name, rtype, ptypes); |
358 } |
385 } |
359 |
386 |
360 /** |
387 /** |
361 * Finds using {@link #findStatic(Class, String, MethodType)} a method on that lookup's class. Useful in classes' |
388 * Finds using {@link #findStatic(Class, String, MethodType)} a method on |
362 * code for convenient linking to their own privates. It's easier to use than {@code findStatic} in that you can |
389 * that lookup's class. Useful in classes' code for convenient linking to |
363 * just list the parameter types, and don't have to specify lookup class. |
390 * their own privates. It's easier to use than {@code findStatic} |
|
391 * in that you can just list the parameter types, and don't have to specify |
|
392 * lookup class. |
364 * @param name the name of the method |
393 * @param name the name of the method |
365 * @param rtype the return type of the method |
394 * @param rtype the return type of the method |
366 * @param ptypes the parameter types of the method |
395 * @param ptypes the parameter types of the method |
367 * @return the method handle for the method |
396 * @return the method handle for the method |
368 */ |
397 */ |