1 /*
2 * Copyright (c) 2008, 2017, Oracle and/or its affiliates. All rights reserved.
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
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
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 *
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.
24 */
25
26 package java.lang.invoke;
27
28 import sun.invoke.util.BytecodeDescriptor;
29 import sun.invoke.util.VerifyAccess;
30
31 import java.lang.reflect.Constructor;
32 import java.lang.reflect.Field;
33 import java.lang.reflect.Member;
34 import java.lang.reflect.Method;
35 import java.lang.reflect.Modifier;
36 import java.util.ArrayList;
37 import java.util.Collections;
38 import java.util.Iterator;
39 import java.util.List;
40 import java.util.Objects;
41
42 import static java.lang.invoke.MethodHandleNatives.Constants.*;
43 import static java.lang.invoke.MethodHandleStatics.newIllegalArgumentException;
44 import static java.lang.invoke.MethodHandleStatics.newInternalError;
45
46 /**
47 * A {@code MemberName} is a compact symbolic datum which fully characterizes
48 * a method or field reference.
49 * A member name refers to a field, method, constructor, or member type.
50 * Every member name has a simple name (a string) and a type (either a Class or MethodType).
51 * A member name may also have a non-null declaring class, or it may be simply
52 * a naked name/type pair.
53 * A member name may also have non-zero modifier flags.
54 * Finally, a member name may be either resolved or unresolved.
55 * If it is resolved, the existence of the named member has been determined by the JVM.
56 * <p>
57 * Whether resolved or not, a member name provides no access rights or
58 * invocation capability to its possessor. It is merely a compact
59 * representation of all symbolic information necessary to link to
60 * and properly use the named member.
61 * <p>
62 * When resolved, a member name's internal implementation may include references to JVM metadata.
63 * This representation is stateless and only descriptive.
64 * It provides no private information and no capability to use the member.
65 * <p>
66 * By contrast, a {@linkplain java.lang.reflect.Method} contains fuller information
67 * about the internals of a method (except its bytecodes) and also
68 * allows invocation. A MemberName is much lighter than a Method,
69 * since it contains about 7 fields to the 16 of Method (plus its sub-arrays),
70 * and those seven fields omit much of the information in Method.
71 * @author jrose
72 */
73 /*non-public*/ final class ResolvedMethodName {
74 //@Injected JVM_Method* vmtarget;
75 //@Injected Class<?> vmholder;
76 };
77
78 /*non-public*/ final class MemberName implements Member, Cloneable {
79 private Class<?> clazz; // class in which the member is defined
80 private String name; // may be null if not yet materialized
81 private Object type; // may be null if not yet materialized
82 private int flags; // modifier bits; see reflect.Modifier
83 private ResolvedMethodName method; // cached resolved method information
84 //@Injected intptr_t vmindex; // vtable index or offset of resolved member
85 Object resolution; // if null, this guy is resolved
86
87 /** Return the declaring class of this member.
88 * In the case of a bare name and type, the declaring class will be null.
89 */
90 public Class<?> getDeclaringClass() {
91 return clazz;
92 }
93
94 /** Utility method producing the class loader of the declaring class. */
95 public ClassLoader getClassLoader() {
96 return clazz.getClassLoader();
97 }
98
99 /** Return the simple name of this member.
100 * For a type, it is the same as {@link Class#getSimpleName}.
101 * For a method or field, it is the simple name of the member.
102 * For a constructor, it is always {@code "<init>"}.
103 */
104 public String getName() {
105 if (name == null) {
106 expandFromVM();
107 if (name == null) {
108 return null;
109 }
110 }
111 return name;
112 }
113
114 public MethodType getMethodOrFieldType() {
115 if (isInvocable())
116 return getMethodType();
117 if (isGetter())
118 return MethodType.methodType(getFieldType());
119 if (isSetter())
120 return MethodType.methodType(void.class, getFieldType());
121 throw new InternalError("not a method or field: "+this);
122 }
123
124 /** Return the declared type of this member, which
125 * must be a method or constructor.
126 */
127 public MethodType getMethodType() {
128 if (type == null) {
129 expandFromVM();
130 if (type == null) {
131 return null;
132 }
133 }
134 if (!isInvocable()) {
135 throw newIllegalArgumentException("not invocable, no method type");
136 }
137
138 {
139 // Get a snapshot of type which doesn't get changed by racing threads.
140 final Object type = this.type;
141 if (type instanceof MethodType) {
142 return (MethodType) type;
143 }
144 }
145
146 // type is not a MethodType yet. Convert it thread-safely.
147 synchronized (this) {
148 if (type instanceof String) {
149 String sig = (String) type;
150 MethodType res = MethodType.fromDescriptor(sig, getClassLoader());
151 type = res;
152 } else if (type instanceof Object[]) {
153 Object[] typeInfo = (Object[]) type;
154 Class<?>[] ptypes = (Class<?>[]) typeInfo[1];
155 Class<?> rtype = (Class<?>) typeInfo[0];
156 MethodType res = MethodType.makeImpl(rtype, ptypes, true);
157 type = res;
158 }
159 // Make sure type is a MethodType for racing threads.
160 assert type instanceof MethodType : "bad method type " + type;
161 }
162 return (MethodType) type;
163 }
164
165 /** Return the descriptor of this member, which
166 * must be a method or constructor.
167 */
168 String getMethodDescriptor() {
169 if (type == null) {
170 expandFromVM();
171 if (type == null) {
172 return null;
173 }
174 }
175 if (!isInvocable()) {
176 throw newIllegalArgumentException("not invocable, no method type");
177 }
178
179 // Get a snapshot of type which doesn't get changed by racing threads.
180 final Object type = this.type;
181 if (type instanceof String) {
182 return (String) type;
183 } else {
184 return getMethodType().toMethodDescriptorString();
185 }
186 }
187
188 /** Return the actual type under which this method or constructor must be invoked.
189 * For non-static methods or constructors, this is the type with a leading parameter,
190 * a reference to declaring class. For static methods, it is the same as the declared type.
191 */
192 public MethodType getInvocationType() {
193 MethodType itype = getMethodOrFieldType();
194 if (isConstructor() && getReferenceKind() == REF_newInvokeSpecial)
195 return itype.changeReturnType(clazz);
196 if (!isStatic())
197 return itype.insertParameterTypes(0, clazz);
198 return itype;
199 }
200
201 /** Utility method producing the parameter types of the method type. */
202 public Class<?>[] getParameterTypes() {
203 return getMethodType().parameterArray();
204 }
205
206 /** Utility method producing the return type of the method type. */
207 public Class<?> getReturnType() {
208 return getMethodType().returnType();
209 }
210
211 /** Return the declared type of this member, which
212 * must be a field or type.
213 * If it is a type member, that type itself is returned.
214 */
215 public Class<?> getFieldType() {
216 if (type == null) {
217 expandFromVM();
218 if (type == null) {
219 return null;
220 }
221 }
222 if (isInvocable()) {
223 throw newIllegalArgumentException("not a field or nested class, no simple type");
224 }
225
226 {
227 // Get a snapshot of type which doesn't get changed by racing threads.
228 final Object type = this.type;
229 if (type instanceof Class<?>) {
230 return (Class<?>) type;
231 }
232 }
233
234 // type is not a Class yet. Convert it thread-safely.
235 synchronized (this) {
236 if (type instanceof String) {
237 String sig = (String) type;
238 MethodType mtype = MethodType.fromDescriptor("()"+sig, getClassLoader());
239 Class<?> res = mtype.returnType();
240 type = res;
241 }
242 // Make sure type is a Class for racing threads.
243 assert type instanceof Class<?> : "bad field type " + type;
244 }
245 return (Class<?>) type;
246 }
247
248 /** Utility method to produce either the method type or field type of this member. */
249 public Object getType() {
250 return (isInvocable() ? getMethodType() : getFieldType());
251 }
252
253 /** Utility method to produce the signature of this member,
254 * used within the class file format to describe its type.
255 */
256 public String getSignature() {
257 if (type == null) {
258 expandFromVM();
259 if (type == null) {
260 return null;
261 }
262 }
263 if (isInvocable())
264 return BytecodeDescriptor.unparse(getMethodType());
265 else
266 return BytecodeDescriptor.unparse(getFieldType());
267 }
268
269 /** Return the modifier flags of this member.
270 * @see java.lang.reflect.Modifier
271 */
272 public int getModifiers() {
273 return (flags & RECOGNIZED_MODIFIERS);
274 }
275
276 /** Return the reference kind of this member, or zero if none.
277 */
278 public byte getReferenceKind() {
279 return (byte) ((flags >>> MN_REFERENCE_KIND_SHIFT) & MN_REFERENCE_KIND_MASK);
280 }
281 private boolean referenceKindIsConsistent() {
282 byte refKind = getReferenceKind();
283 if (refKind == REF_NONE) return isType();
284 if (isField()) {
285 assert(staticIsConsistent());
286 assert(MethodHandleNatives.refKindIsField(refKind));
287 } else if (isConstructor()) {
288 assert(refKind == REF_newInvokeSpecial || refKind == REF_invokeSpecial);
289 } else if (isMethod()) {
290 assert(staticIsConsistent());
291 assert(MethodHandleNatives.refKindIsMethod(refKind));
292 if (clazz.isInterface())
293 assert(refKind == REF_invokeInterface ||
294 refKind == REF_invokeStatic ||
295 refKind == REF_invokeSpecial ||
296 refKind == REF_invokeVirtual && isObjectPublicMethod());
297 } else {
298 assert(false);
299 }
300 return true;
301 }
302 private boolean isObjectPublicMethod() {
303 if (clazz == Object.class) return true;
304 MethodType mtype = getMethodType();
305 if (name.equals("toString") && mtype.returnType() == String.class && mtype.parameterCount() == 0)
306 return true;
307 if (name.equals("hashCode") && mtype.returnType() == int.class && mtype.parameterCount() == 0)
308 return true;
309 if (name.equals("equals") && mtype.returnType() == boolean.class && mtype.parameterCount() == 1 && mtype.parameterType(0) == Object.class)
310 return true;
311 return false;
312 }
313 /*non-public*/ boolean referenceKindIsConsistentWith(int originalRefKind) {
314 int refKind = getReferenceKind();
315 if (refKind == originalRefKind) return true;
316 switch (originalRefKind) {
317 case REF_invokeInterface:
318 // Looking up an interface method, can get (e.g.) Object.hashCode
319 assert(refKind == REF_invokeVirtual ||
320 refKind == REF_invokeSpecial) : this;
321 return true;
322 case REF_invokeVirtual:
323 case REF_newInvokeSpecial:
324 // Looked up a virtual, can get (e.g.) final String.hashCode.
325 assert(refKind == REF_invokeSpecial) : this;
326 return true;
327 }
328 assert(false) : this+" != "+MethodHandleNatives.refKindName((byte)originalRefKind);
329 return true;
330 }
331 private boolean staticIsConsistent() {
332 byte refKind = getReferenceKind();
333 return MethodHandleNatives.refKindIsStatic(refKind) == isStatic() || getModifiers() == 0;
334 }
335 private boolean vminfoIsConsistent() {
336 byte refKind = getReferenceKind();
337 assert(isResolved()); // else don't call
338 Object vminfo = MethodHandleNatives.getMemberVMInfo(this);
339 assert(vminfo instanceof Object[]);
340 long vmindex = (Long) ((Object[])vminfo)[0];
341 Object vmtarget = ((Object[])vminfo)[1];
342 if (MethodHandleNatives.refKindIsField(refKind)) {
343 assert(vmindex >= 0) : vmindex + ":" + this;
344 assert(vmtarget instanceof Class);
345 } else {
346 if (MethodHandleNatives.refKindDoesDispatch(refKind))
347 assert(vmindex >= 0) : vmindex + ":" + this;
348 else
349 assert(vmindex < 0) : vmindex;
350 assert(vmtarget instanceof MemberName) : vmtarget + " in " + this;
351 }
352 return true;
353 }
354
355 private MemberName changeReferenceKind(byte refKind, byte oldKind) {
356 assert(getReferenceKind() == oldKind);
357 assert(MethodHandleNatives.refKindIsValid(refKind));
358 flags += (((int)refKind - oldKind) << MN_REFERENCE_KIND_SHIFT);
359 return this;
360 }
361
362 private boolean testFlags(int mask, int value) {
363 return (flags & mask) == value;
364 }
365 private boolean testAllFlags(int mask) {
366 return testFlags(mask, mask);
367 }
368 private boolean testAnyFlags(int mask) {
369 return !testFlags(mask, 0);
370 }
371
372 /** Utility method to query if this member is a method handle invocation (invoke or invokeExact).
373 */
374 public boolean isMethodHandleInvoke() {
375 final int bits = MH_INVOKE_MODS &~ Modifier.PUBLIC;
376 final int negs = Modifier.STATIC;
377 if (testFlags(bits | negs, bits) &&
378 clazz == MethodHandle.class) {
379 return isMethodHandleInvokeName(name);
380 }
381 return false;
382 }
383 public static boolean isMethodHandleInvokeName(String name) {
384 switch (name) {
385 case "invoke":
386 case "invokeExact":
387 return true;
388 default:
389 return false;
390 }
391 }
392 public boolean isVarHandleMethodInvoke() {
393 final int bits = MH_INVOKE_MODS &~ Modifier.PUBLIC;
394 final int negs = Modifier.STATIC;
395 if (testFlags(bits | negs, bits) &&
396 clazz == VarHandle.class) {
397 return isVarHandleMethodInvokeName(name);
398 }
399 return false;
400 }
401 public static boolean isVarHandleMethodInvokeName(String name) {
402 try {
403 VarHandle.AccessMode.valueFromMethodName(name);
404 return true;
405 } catch (IllegalArgumentException e) {
406 return false;
407 }
408 }
409 private static final int MH_INVOKE_MODS = Modifier.NATIVE | Modifier.FINAL | Modifier.PUBLIC;
410
411 /** Utility method to query the modifier flags of this member. */
412 public boolean isStatic() {
413 return Modifier.isStatic(flags);
414 }
415 /** Utility method to query the modifier flags of this member. */
416 public boolean isPublic() {
417 return Modifier.isPublic(flags);
418 }
419 /** Utility method to query the modifier flags of this member. */
420 public boolean isPrivate() {
421 return Modifier.isPrivate(flags);
422 }
423 /** Utility method to query the modifier flags of this member. */
424 public boolean isProtected() {
425 return Modifier.isProtected(flags);
426 }
427 /** Utility method to query the modifier flags of this member. */
428 public boolean isFinal() {
429 return Modifier.isFinal(flags);
430 }
431 /** Utility method to query whether this member or its defining class is final. */
432 public boolean canBeStaticallyBound() {
433 return Modifier.isFinal(flags | clazz.getModifiers());
434 }
435 /** Utility method to query the modifier flags of this member. */
436 public boolean isVolatile() {
437 return Modifier.isVolatile(flags);
438 }
439 /** Utility method to query the modifier flags of this member. */
440 public boolean isAbstract() {
441 return Modifier.isAbstract(flags);
442 }
443 /** Utility method to query the modifier flags of this member. */
444 public boolean isNative() {
445 return Modifier.isNative(flags);
446 }
447 // let the rest (native, volatile, transient, etc.) be tested via Modifier.isFoo
448
449 // unofficial modifier flags, used by HotSpot:
450 static final int BRIDGE = 0x00000040;
451 static final int VARARGS = 0x00000080;
452 static final int SYNTHETIC = 0x00001000;
453 static final int ANNOTATION= 0x00002000;
454 static final int ENUM = 0x00004000;
455 /** Utility method to query the modifier flags of this member; returns false if the member is not a method. */
456 public boolean isBridge() {
457 return testAllFlags(IS_METHOD | BRIDGE);
458 }
459 /** Utility method to query the modifier flags of this member; returns false if the member is not a method. */
460 public boolean isVarargs() {
461 return testAllFlags(VARARGS) && isInvocable();
462 }
463 /** Utility method to query the modifier flags of this member; returns false if the member is not a method. */
464 public boolean isSynthetic() {
465 return testAllFlags(SYNTHETIC);
466 }
467
468 static final String CONSTRUCTOR_NAME = "<init>"; // the ever-popular
469
470 // modifiers exported by the JVM:
471 static final int RECOGNIZED_MODIFIERS = 0xFFFF;
472
473 // private flags, not part of RECOGNIZED_MODIFIERS:
474 static final int
475 IS_METHOD = MN_IS_METHOD, // method (not constructor)
476 IS_CONSTRUCTOR = MN_IS_CONSTRUCTOR, // constructor
477 IS_FIELD = MN_IS_FIELD, // field
478 IS_TYPE = MN_IS_TYPE, // nested type
479 CALLER_SENSITIVE = MN_CALLER_SENSITIVE; // @CallerSensitive annotation detected
480
481 static final int ALL_ACCESS = Modifier.PUBLIC | Modifier.PRIVATE | Modifier.PROTECTED;
482 static final int ALL_KINDS = IS_METHOD | IS_CONSTRUCTOR | IS_FIELD | IS_TYPE;
483 static final int IS_INVOCABLE = IS_METHOD | IS_CONSTRUCTOR;
484 static final int IS_FIELD_OR_METHOD = IS_METHOD | IS_FIELD;
485 static final int SEARCH_ALL_SUPERS = MN_SEARCH_SUPERCLASSES | MN_SEARCH_INTERFACES;
486
487 /** Utility method to query whether this member is a method or constructor. */
488 public boolean isInvocable() {
489 return testAnyFlags(IS_INVOCABLE);
490 }
491 /** Utility method to query whether this member is a method, constructor, or field. */
492 public boolean isFieldOrMethod() {
493 return testAnyFlags(IS_FIELD_OR_METHOD);
494 }
495 /** Query whether this member is a method. */
496 public boolean isMethod() {
497 return testAllFlags(IS_METHOD);
498 }
499 /** Query whether this member is a constructor. */
500 public boolean isConstructor() {
501 return testAllFlags(IS_CONSTRUCTOR);
502 }
503 /** Query whether this member is a field. */
504 public boolean isField() {
505 return testAllFlags(IS_FIELD);
506 }
507 /** Query whether this member is a type. */
508 public boolean isType() {
509 return testAllFlags(IS_TYPE);
510 }
511 /** Utility method to query whether this member is neither public, private, nor protected. */
512 public boolean isPackage() {
513 return !testAnyFlags(ALL_ACCESS);
514 }
515 /** Query whether this member has a CallerSensitive annotation. */
516 public boolean isCallerSensitive() {
517 return testAllFlags(CALLER_SENSITIVE);
518 }
519
520 /** Utility method to query whether this member is accessible from a given lookup class. */
521 public boolean isAccessibleFrom(Class<?> lookupClass) {
522 int mode = (ALL_ACCESS|MethodHandles.Lookup.PACKAGE|MethodHandles.Lookup.MODULE);
523 return VerifyAccess.isMemberAccessible(this.getDeclaringClass(), this.getDeclaringClass(), flags,
524 lookupClass, mode);
525 }
526
527 /**
528 * Check if MemberName is a call to a method named {@code name} in class {@code declaredClass}.
529 */
530 public boolean refersTo(Class<?> declc, String n) {
531 return clazz == declc && getName().equals(n);
532 }
533
534 /** Initialize a query. It is not resolved. */
535 private void init(Class<?> defClass, String name, Object type, int flags) {
536 // defining class is allowed to be null (for a naked name/type pair)
537 //name.toString(); // null check
538 //type.equals(type); // null check
539 // fill in fields:
540 this.clazz = defClass;
541 this.name = name;
542 this.type = type;
543 this.flags = flags;
544 assert(testAnyFlags(ALL_KINDS));
545 assert(this.resolution == null); // nobody should have touched this yet
546 //assert(referenceKindIsConsistent()); // do this after resolution
547 }
548
549 /**
550 * Calls down to the VM to fill in the fields. This method is
551 * synchronized to avoid racing calls.
552 */
553 private void expandFromVM() {
554 if (type != null) {
555 return;
556 }
557 if (!isResolved()) {
558 return;
559 }
560 MethodHandleNatives.expand(this);
561 }
562
563 // Capturing information from the Core Reflection API:
564 private static int flagsMods(int flags, int mods, byte refKind) {
565 assert((flags & RECOGNIZED_MODIFIERS) == 0);
566 assert((mods & ~RECOGNIZED_MODIFIERS) == 0);
567 assert((refKind & ~MN_REFERENCE_KIND_MASK) == 0);
568 return flags | mods | (refKind << MN_REFERENCE_KIND_SHIFT);
569 }
570 /** Create a name for the given reflected method. The resulting name will be in a resolved state. */
571 public MemberName(Method m) {
572 this(m, false);
573 }
574 @SuppressWarnings("LeakingThisInConstructor")
575 public MemberName(Method m, boolean wantSpecial) {
576 Objects.requireNonNull(m);
577 // fill in vmtarget, vmindex while we have m in hand:
578 MethodHandleNatives.init(this, m);
579 if (clazz == null) { // MHN.init failed
580 if (m.getDeclaringClass() == MethodHandle.class &&
581 isMethodHandleInvokeName(m.getName())) {
582 // The JVM did not reify this signature-polymorphic instance.
583 // Need a special case here.
584 // See comments on MethodHandleNatives.linkMethod.
585 MethodType type = MethodType.methodType(m.getReturnType(), m.getParameterTypes());
586 int flags = flagsMods(IS_METHOD, m.getModifiers(), REF_invokeVirtual);
587 init(MethodHandle.class, m.getName(), type, flags);
588 if (isMethodHandleInvoke())
589 return;
590 }
591 if (m.getDeclaringClass() == VarHandle.class &&
592 isVarHandleMethodInvokeName(m.getName())) {
593 // The JVM did not reify this signature-polymorphic instance.
594 // Need a special case here.
595 // See comments on MethodHandleNatives.linkMethod.
596 MethodType type = MethodType.methodType(m.getReturnType(), m.getParameterTypes());
597 int flags = flagsMods(IS_METHOD, m.getModifiers(), REF_invokeVirtual);
598 init(VarHandle.class, m.getName(), type, flags);
599 if (isVarHandleMethodInvoke())
600 return;
601 }
602 throw new LinkageError(m.toString());
603 }
604 assert(isResolved() && this.clazz != null);
605 this.name = m.getName();
606 if (this.type == null)
607 this.type = new Object[] { m.getReturnType(), m.getParameterTypes() };
608 if (wantSpecial) {
609 if (isAbstract())
610 throw new AbstractMethodError(this.toString());
611 if (getReferenceKind() == REF_invokeVirtual)
612 changeReferenceKind(REF_invokeSpecial, REF_invokeVirtual);
613 else if (getReferenceKind() == REF_invokeInterface)
614 // invokeSpecial on a default method
615 changeReferenceKind(REF_invokeSpecial, REF_invokeInterface);
616 }
617 }
618 public MemberName asSpecial() {
619 switch (getReferenceKind()) {
620 case REF_invokeSpecial: return this;
621 case REF_invokeVirtual: return clone().changeReferenceKind(REF_invokeSpecial, REF_invokeVirtual);
622 case REF_invokeInterface: return clone().changeReferenceKind(REF_invokeSpecial, REF_invokeInterface);
623 case REF_newInvokeSpecial: return clone().changeReferenceKind(REF_invokeSpecial, REF_newInvokeSpecial);
624 }
625 throw new IllegalArgumentException(this.toString());
626 }
627 /** If this MN is not REF_newInvokeSpecial, return a clone with that ref. kind.
628 * In that case it must already be REF_invokeSpecial.
629 */
630 public MemberName asConstructor() {
631 switch (getReferenceKind()) {
632 case REF_invokeSpecial: return clone().changeReferenceKind(REF_newInvokeSpecial, REF_invokeSpecial);
633 case REF_newInvokeSpecial: return this;
634 }
635 throw new IllegalArgumentException(this.toString());
636 }
637 /** If this MN is a REF_invokeSpecial, return a clone with the "normal" kind
638 * REF_invokeVirtual; also switch either to REF_invokeInterface if clazz.isInterface.
639 * The end result is to get a fully virtualized version of the MN.
640 * (Note that resolving in the JVM will sometimes devirtualize, changing
641 * REF_invokeVirtual of a final to REF_invokeSpecial, and REF_invokeInterface
642 * in some corner cases to either of the previous two; this transform
643 * undoes that change under the assumption that it occurred.)
644 */
645 public MemberName asNormalOriginal() {
646 byte normalVirtual = clazz.isInterface() ? REF_invokeInterface : REF_invokeVirtual;
647 byte refKind = getReferenceKind();
648 byte newRefKind = refKind;
649 MemberName result = this;
650 switch (refKind) {
651 case REF_invokeInterface:
652 case REF_invokeVirtual:
653 case REF_invokeSpecial:
654 newRefKind = normalVirtual;
655 break;
656 }
657 if (newRefKind == refKind)
658 return this;
659 result = clone().changeReferenceKind(newRefKind, refKind);
660 assert(this.referenceKindIsConsistentWith(result.getReferenceKind()));
661 return result;
662 }
663 /** Create a name for the given reflected constructor. The resulting name will be in a resolved state. */
664 @SuppressWarnings("LeakingThisInConstructor")
665 public MemberName(Constructor<?> ctor) {
666 Objects.requireNonNull(ctor);
667 // fill in vmtarget, vmindex while we have ctor in hand:
668 MethodHandleNatives.init(this, ctor);
669 assert(isResolved() && this.clazz != null);
670 this.name = CONSTRUCTOR_NAME;
671 if (this.type == null)
672 this.type = new Object[] { void.class, ctor.getParameterTypes() };
673 }
674 /** Create a name for the given reflected field. The resulting name will be in a resolved state.
675 */
676 public MemberName(Field fld) {
677 this(fld, false);
678 }
679 @SuppressWarnings("LeakingThisInConstructor")
680 public MemberName(Field fld, boolean makeSetter) {
681 Objects.requireNonNull(fld);
682 // fill in vmtarget, vmindex while we have fld in hand:
683 MethodHandleNatives.init(this, fld);
684 assert(isResolved() && this.clazz != null);
685 this.name = fld.getName();
686 this.type = fld.getType();
687 assert((REF_putStatic - REF_getStatic) == (REF_putField - REF_getField));
688 byte refKind = this.getReferenceKind();
689 assert(refKind == (isStatic() ? REF_getStatic : REF_getField));
690 if (makeSetter) {
691 changeReferenceKind((byte)(refKind + (REF_putStatic - REF_getStatic)), refKind);
692 }
693 }
694 public boolean isGetter() {
695 return MethodHandleNatives.refKindIsGetter(getReferenceKind());
696 }
697 public boolean isSetter() {
698 return MethodHandleNatives.refKindIsSetter(getReferenceKind());
699 }
700 public MemberName asSetter() {
701 byte refKind = getReferenceKind();
702 assert(MethodHandleNatives.refKindIsGetter(refKind));
703 assert((REF_putStatic - REF_getStatic) == (REF_putField - REF_getField));
704 byte setterRefKind = (byte)(refKind + (REF_putField - REF_getField));
705 return clone().changeReferenceKind(setterRefKind, refKind);
706 }
707 /** Create a name for the given class. The resulting name will be in a resolved state. */
708 public MemberName(Class<?> type) {
709 init(type.getDeclaringClass(), type.getSimpleName(), type,
710 flagsMods(IS_TYPE, type.getModifiers(), REF_NONE));
711 initResolved(true);
712 }
713
714 /**
715 * Create a name for a signature-polymorphic invoker.
716 * This is a placeholder for a signature-polymorphic instance
717 * (of MH.invokeExact, etc.) that the JVM does not reify.
718 * See comments on {@link MethodHandleNatives#linkMethod}.
719 */
720 static MemberName makeMethodHandleInvoke(String name, MethodType type) {
721 return makeMethodHandleInvoke(name, type, MH_INVOKE_MODS | SYNTHETIC);
722 }
723 static MemberName makeMethodHandleInvoke(String name, MethodType type, int mods) {
724 MemberName mem = new MemberName(MethodHandle.class, name, type, REF_invokeVirtual);
725 mem.flags |= mods; // it's not resolved, but add these modifiers anyway
726 assert(mem.isMethodHandleInvoke()) : mem;
727 return mem;
728 }
729
730 static MemberName makeVarHandleMethodInvoke(String name, MethodType type) {
731 return makeVarHandleMethodInvoke(name, type, MH_INVOKE_MODS | SYNTHETIC);
732 }
733 static MemberName makeVarHandleMethodInvoke(String name, MethodType type, int mods) {
734 MemberName mem = new MemberName(VarHandle.class, name, type, REF_invokeVirtual);
735 mem.flags |= mods; // it's not resolved, but add these modifiers anyway
736 assert(mem.isVarHandleMethodInvoke()) : mem;
737 return mem;
738 }
739
740 // bare-bones constructor; the JVM will fill it in
741 MemberName() { }
742
743 // locally useful cloner
744 @Override protected MemberName clone() {
745 try {
746 return (MemberName) super.clone();
747 } catch (CloneNotSupportedException ex) {
748 throw newInternalError(ex);
749 }
750 }
751
752 /** Get the definition of this member name.
753 * This may be in a super-class of the declaring class of this member.
754 */
755 public MemberName getDefinition() {
756 if (!isResolved()) throw new IllegalStateException("must be resolved: "+this);
757 if (isType()) return this;
758 MemberName res = this.clone();
759 res.clazz = null;
760 res.type = null;
761 res.name = null;
762 res.resolution = res;
763 res.expandFromVM();
764 assert(res.getName().equals(this.getName()));
765 return res;
766 }
767
768 @Override
769 @SuppressWarnings("deprecation")
770 public int hashCode() {
771 // Avoid autoboxing getReferenceKind(), since this is used early and will force
772 // early initialization of Byte$ByteCache
773 return Objects.hash(clazz, new Byte(getReferenceKind()), name, getType());
774 }
775
776 @Override
777 public boolean equals(Object that) {
778 return (that instanceof MemberName && this.equals((MemberName)that));
779 }
780
781 /** Decide if two member names have exactly the same symbolic content.
782 * Does not take into account any actual class members, so even if
783 * two member names resolve to the same actual member, they may
784 * be distinct references.
785 */
786 public boolean equals(MemberName that) {
787 if (this == that) return true;
788 if (that == null) return false;
789 return this.clazz == that.clazz
790 && this.getReferenceKind() == that.getReferenceKind()
791 && Objects.equals(this.name, that.name)
792 && Objects.equals(this.getType(), that.getType());
793 }
794
795 // Construction from symbolic parts, for queries:
796 /** Create a field or type name from the given components:
797 * Declaring class, name, type, reference kind.
798 * The declaring class may be supplied as null if this is to be a bare name and type.
799 * The resulting name will in an unresolved state.
800 */
801 public MemberName(Class<?> defClass, String name, Class<?> type, byte refKind) {
802 init(defClass, name, type, flagsMods(IS_FIELD, 0, refKind));
803 initResolved(false);
804 }
805 /** Create a method or constructor name from the given components:
806 * Declaring class, name, type, reference kind.
807 * It will be a constructor if and only if the name is {@code "<init>"}.
808 * The declaring class may be supplied as null if this is to be a bare name and type.
809 * The last argument is optional, a boolean which requests REF_invokeSpecial.
810 * The resulting name will in an unresolved state.
811 */
812 public MemberName(Class<?> defClass, String name, MethodType type, byte refKind) {
813 int initFlags = (name != null && name.equals(CONSTRUCTOR_NAME) ? IS_CONSTRUCTOR : IS_METHOD);
814 init(defClass, name, type, flagsMods(initFlags, 0, refKind));
815 initResolved(false);
816 }
817 /** Create a method, constructor, or field name from the given components:
818 * Reference kind, declaring class, name, type.
819 */
820 public MemberName(byte refKind, Class<?> defClass, String name, Object type) {
821 int kindFlags;
822 if (MethodHandleNatives.refKindIsField(refKind)) {
823 kindFlags = IS_FIELD;
824 if (!(type instanceof Class))
825 throw newIllegalArgumentException("not a field type");
826 } else if (MethodHandleNatives.refKindIsMethod(refKind)) {
827 kindFlags = IS_METHOD;
828 if (!(type instanceof MethodType))
829 throw newIllegalArgumentException("not a method type");
830 } else if (refKind == REF_newInvokeSpecial) {
831 kindFlags = IS_CONSTRUCTOR;
832 if (!(type instanceof MethodType) ||
833 !CONSTRUCTOR_NAME.equals(name))
834 throw newIllegalArgumentException("not a constructor type or name");
835 } else {
836 throw newIllegalArgumentException("bad reference kind "+refKind);
837 }
838 init(defClass, name, type, flagsMods(kindFlags, 0, refKind));
839 initResolved(false);
840 }
841 /** Query whether this member name is resolved to a non-static, non-final method.
842 */
843 public boolean hasReceiverTypeDispatch() {
844 return MethodHandleNatives.refKindDoesDispatch(getReferenceKind());
845 }
846
847 /** Query whether this member name is resolved.
848 * A resolved member name is one for which the JVM has found
849 * a method, constructor, field, or type binding corresponding exactly to the name.
850 * (Document?)
851 */
852 public boolean isResolved() {
853 return resolution == null;
854 }
855
856 void initResolved(boolean isResolved) {
857 assert(this.resolution == null); // not initialized yet!
858 if (!isResolved)
859 this.resolution = this;
860 assert(isResolved() == isResolved);
861 }
862
863 void checkForTypeAlias(Class<?> refc) {
864 if (isInvocable()) {
865 MethodType type;
866 if (this.type instanceof MethodType)
867 type = (MethodType) this.type;
868 else
869 this.type = type = getMethodType();
870 if (type.erase() == type) return;
871 if (VerifyAccess.isTypeVisible(type, refc)) return;
872 throw new LinkageError("bad method type alias: "+type+" not visible from "+refc);
873 } else {
874 Class<?> type;
875 if (this.type instanceof Class<?>)
876 type = (Class<?>) this.type;
877 else
878 this.type = type = getFieldType();
879 if (VerifyAccess.isTypeVisible(type, refc)) return;
880 throw new LinkageError("bad field type alias: "+type+" not visible from "+refc);
881 }
882 }
883
884
885 /** Produce a string form of this member name.
886 * For types, it is simply the type's own string (as reported by {@code toString}).
887 * For fields, it is {@code "DeclaringClass.name/type"}.
888 * For methods and constructors, it is {@code "DeclaringClass.name(ptype...)rtype"}.
889 * If the declaring class is null, the prefix {@code "DeclaringClass."} is omitted.
890 * If the member is unresolved, a prefix {@code "*."} is prepended.
891 */
892 @SuppressWarnings("LocalVariableHidesMemberVariable")
893 @Override
894 public String toString() {
895 if (isType())
896 return type.toString(); // class java.lang.String
897 // else it is a field, method, or constructor
898 StringBuilder buf = new StringBuilder();
899 if (getDeclaringClass() != null) {
900 buf.append(getName(clazz));
901 buf.append('.');
902 }
903 String name = this.name; // avoid expanding from VM
904 buf.append(name == null ? "*" : name);
905 Object type = this.type; // avoid expanding from VM
906 if (!isInvocable()) {
907 buf.append('/');
908 buf.append(type == null ? "*" : getName(type));
909 } else {
910 buf.append(type == null ? "(*)*" : getName(type));
911 }
912 byte refKind = getReferenceKind();
913 if (refKind != REF_NONE) {
914 buf.append('/');
915 buf.append(MethodHandleNatives.refKindName(refKind));
916 }
917 //buf.append("#").append(System.identityHashCode(this));
918 return buf.toString();
919 }
920 private static String getName(Object obj) {
921 if (obj instanceof Class<?>)
922 return ((Class<?>)obj).getName();
923 return String.valueOf(obj);
924 }
925
926 public IllegalAccessException makeAccessException(String message, Object from) {
927 message = message + ": "+ toString();
928 if (from != null) {
929 if (from == MethodHandles.publicLookup()) {
930 message += ", from public Lookup";
931 } else {
932 Module m;
933 if (from instanceof MethodHandles.Lookup) {
934 MethodHandles.Lookup lookup = (MethodHandles.Lookup)from;
935 m = lookup.lookupClass().getModule();
936 } else {
937 m = from.getClass().getModule();
938 }
939 message += ", from " + from + " (" + m + ")";
940 }
941 }
942 return new IllegalAccessException(message);
943 }
944 private String message() {
945 if (isResolved())
946 return "no access";
947 else if (isConstructor())
948 return "no such constructor";
949 else if (isMethod())
950 return "no such method";
951 else
952 return "no such field";
953 }
954 public ReflectiveOperationException makeAccessException() {
955 String message = message() + ": "+ toString();
956 ReflectiveOperationException ex;
957 if (isResolved() || !(resolution instanceof NoSuchMethodError ||
958 resolution instanceof NoSuchFieldError))
959 ex = new IllegalAccessException(message);
960 else if (isConstructor())
961 ex = new NoSuchMethodException(message);
962 else if (isMethod())
963 ex = new NoSuchMethodException(message);
964 else
965 ex = new NoSuchFieldException(message);
966 if (resolution instanceof Throwable)
967 ex.initCause((Throwable) resolution);
968 return ex;
969 }
970
971 /** Actually making a query requires an access check. */
972 /*non-public*/ static Factory getFactory() {
973 return Factory.INSTANCE;
974 }
975 /** A factory type for resolving member names with the help of the VM.
976 * TBD: Define access-safe public constructors for this factory.
977 */
978 /*non-public*/ static class Factory {
979 private Factory() { } // singleton pattern
980 static Factory INSTANCE = new Factory();
981
982 private static int ALLOWED_FLAGS = ALL_KINDS;
983
984 /// Queries
985 List<MemberName> getMembers(Class<?> defc,
986 String matchName, Object matchType,
987 int matchFlags, Class<?> lookupClass) {
988 matchFlags &= ALLOWED_FLAGS;
989 String matchSig = null;
990 if (matchType != null) {
991 matchSig = BytecodeDescriptor.unparse(matchType);
992 if (matchSig.startsWith("("))
993 matchFlags &= ~(ALL_KINDS & ~IS_INVOCABLE);
994 else
995 matchFlags &= ~(ALL_KINDS & ~IS_FIELD);
996 }
997 final int BUF_MAX = 0x2000;
998 int len1 = matchName == null ? 10 : matchType == null ? 4 : 1;
999 MemberName[] buf = newMemberBuffer(len1);
1000 int totalCount = 0;
1001 ArrayList<MemberName[]> bufs = null;
1002 int bufCount = 0;
1003 for (;;) {
1004 bufCount = MethodHandleNatives.getMembers(defc,
1005 matchName, matchSig, matchFlags,
1006 lookupClass,
1007 totalCount, buf);
1008 if (bufCount <= buf.length) {
1009 if (bufCount < 0) bufCount = 0;
1010 totalCount += bufCount;
1011 break;
1012 }
1013 // JVM returned to us with an intentional overflow!
1014 totalCount += buf.length;
1015 int excess = bufCount - buf.length;
1016 if (bufs == null) bufs = new ArrayList<>(1);
1017 bufs.add(buf);
1018 int len2 = buf.length;
1019 len2 = Math.max(len2, excess);
1020 len2 = Math.max(len2, totalCount / 4);
1021 buf = newMemberBuffer(Math.min(BUF_MAX, len2));
1022 }
1023 ArrayList<MemberName> result = new ArrayList<>(totalCount);
1024 if (bufs != null) {
1025 for (MemberName[] buf0 : bufs) {
1026 Collections.addAll(result, buf0);
1027 }
1028 }
1029 for (int i = 0; i < bufCount; i++) {
1030 result.add(buf[i]);
1031 }
1032 // Signature matching is not the same as type matching, since
1033 // one signature might correspond to several types.
1034 // So if matchType is a Class or MethodType, refilter the results.
1035 if (matchType != null && matchType != matchSig) {
1036 for (Iterator<MemberName> it = result.iterator(); it.hasNext();) {
1037 MemberName m = it.next();
1038 if (!matchType.equals(m.getType()))
1039 it.remove();
1040 }
1041 }
1042 return result;
1043 }
1044 /** Produce a resolved version of the given member.
1045 * Super types are searched (for inherited members) if {@code searchSupers} is true.
1046 * Access checking is performed on behalf of the given {@code lookupClass}.
1047 * If lookup fails or access is not permitted, null is returned.
1048 * Otherwise a fresh copy of the given member is returned, with modifier bits filled in.
1049 */
1050 private MemberName resolve(byte refKind, MemberName ref, Class<?> lookupClass) {
1051 MemberName m = ref.clone(); // JVM will side-effect the ref
1052 assert(refKind == m.getReferenceKind());
1053 try {
1054 // There are 4 entities in play here:
1055 // * LC: lookupClass
1056 // * REFC: symbolic reference class (MN.clazz before resolution);
1057 // * DEFC: resolved method holder (MN.clazz after resolution);
1058 // * PTYPES: parameter types (MN.type)
1059 //
1060 // What we care about when resolving a MemberName is consistency between DEFC and PTYPES.
1061 // We do type alias (TA) checks on DEFC to ensure that. DEFC is not known until the JVM
1062 // finishes the resolution, so do TA checks right after MHN.resolve() is over.
1063 //
1064 // All parameters passed by a caller are checked against MH type (PTYPES) on every invocation,
1065 // so it is safe to call a MH from any context.
1066 //
1067 // REFC view on PTYPES doesn't matter, since it is used only as a starting point for resolution and doesn't
1068 // participate in method selection.
1069 m = MethodHandleNatives.resolve(m, lookupClass);
1070 m.checkForTypeAlias(m.getDeclaringClass());
1071 m.resolution = null;
1072 } catch (ClassNotFoundException | LinkageError ex) {
1073 // JVM reports that the "bytecode behavior" would get an error
1074 assert(!m.isResolved());
1075 m.resolution = ex;
1076 return m;
1077 }
1078 assert(m.referenceKindIsConsistent());
1079 m.initResolved(true);
1080 assert(m.vminfoIsConsistent());
1081 return m;
1082 }
1083 /** Produce a resolved version of the given member.
1084 * Super types are searched (for inherited members) if {@code searchSupers} is true.
1085 * Access checking is performed on behalf of the given {@code lookupClass}.
1086 * If lookup fails or access is not permitted, a {@linkplain ReflectiveOperationException} is thrown.
1087 * Otherwise a fresh copy of the given member is returned, with modifier bits filled in.
1088 */
1089 public
1090 <NoSuchMemberException extends ReflectiveOperationException>
1091 MemberName resolveOrFail(byte refKind, MemberName m, Class<?> lookupClass,
1092 Class<NoSuchMemberException> nsmClass)
1093 throws IllegalAccessException, NoSuchMemberException {
1094 MemberName result = resolve(refKind, m, lookupClass);
1095 if (result.isResolved())
1096 return result;
1097 ReflectiveOperationException ex = result.makeAccessException();
1098 if (ex instanceof IllegalAccessException) throw (IllegalAccessException) ex;
1099 throw nsmClass.cast(ex);
1100 }
1101 /** Produce a resolved version of the given member.
1102 * Super types are searched (for inherited members) if {@code searchSupers} is true.
1103 * Access checking is performed on behalf of the given {@code lookupClass}.
1104 * If lookup fails or access is not permitted, return null.
1105 * Otherwise a fresh copy of the given member is returned, with modifier bits filled in.
1106 */
1107 public
1108 MemberName resolveOrNull(byte refKind, MemberName m, Class<?> lookupClass) {
1109 MemberName result = resolve(refKind, m, lookupClass);
1110 if (result.isResolved())
1111 return result;
1112 return null;
1113 }
1114 /** Return a list of all methods defined by the given class.
1115 * Super types are searched (for inherited members) if {@code searchSupers} is true.
1116 * Access checking is performed on behalf of the given {@code lookupClass}.
1117 * Inaccessible members are not added to the last.
1118 */
1119 public List<MemberName> getMethods(Class<?> defc, boolean searchSupers,
1120 Class<?> lookupClass) {
1121 return getMethods(defc, searchSupers, null, null, lookupClass);
1122 }
1123 /** Return a list of matching methods defined by the given class.
1124 * Super types are searched (for inherited members) if {@code searchSupers} is true.
1125 * Returned methods will match the name (if not null) and the type (if not null).
1126 * Access checking is performed on behalf of the given {@code lookupClass}.
1127 * Inaccessible members are not added to the last.
1128 */
1129 public List<MemberName> getMethods(Class<?> defc, boolean searchSupers,
1130 String name, MethodType type, Class<?> lookupClass) {
1131 int matchFlags = IS_METHOD | (searchSupers ? SEARCH_ALL_SUPERS : 0);
1132 return getMembers(defc, name, type, matchFlags, lookupClass);
1133 }
1134 /** Return a list of all constructors defined by the given class.
1135 * Access checking is performed on behalf of the given {@code lookupClass}.
1136 * Inaccessible members are not added to the last.
1137 */
1138 public List<MemberName> getConstructors(Class<?> defc, Class<?> lookupClass) {
1139 return getMembers(defc, null, null, IS_CONSTRUCTOR, lookupClass);
1140 }
1141 /** Return a list of all fields defined by the given class.
1142 * Super types are searched (for inherited members) if {@code searchSupers} is true.
1143 * Access checking is performed on behalf of the given {@code lookupClass}.
1144 * Inaccessible members are not added to the last.
1145 */
1146 public List<MemberName> getFields(Class<?> defc, boolean searchSupers,
1147 Class<?> lookupClass) {
1148 return getFields(defc, searchSupers, null, null, lookupClass);
1149 }
1150 /** Return a list of all fields defined by the given class.
1151 * Super types are searched (for inherited members) if {@code searchSupers} is true.
1152 * Returned fields will match the name (if not null) and the type (if not null).
1153 * Access checking is performed on behalf of the given {@code lookupClass}.
1154 * Inaccessible members are not added to the last.
1155 */
1156 public List<MemberName> getFields(Class<?> defc, boolean searchSupers,
1157 String name, Class<?> type, Class<?> lookupClass) {
1158 int matchFlags = IS_FIELD | (searchSupers ? SEARCH_ALL_SUPERS : 0);
1159 return getMembers(defc, name, type, matchFlags, lookupClass);
1160 }
1161 /** Return a list of all nested types defined by the given class.
1162 * Super types are searched (for inherited members) if {@code searchSupers} is true.
1163 * Access checking is performed on behalf of the given {@code lookupClass}.
1164 * Inaccessible members are not added to the last.
1165 */
1166 public List<MemberName> getNestedTypes(Class<?> defc, boolean searchSupers,
1167 Class<?> lookupClass) {
1168 int matchFlags = IS_TYPE | (searchSupers ? SEARCH_ALL_SUPERS : 0);
1169 return getMembers(defc, null, null, matchFlags, lookupClass);
1170 }
1171 private static MemberName[] newMemberBuffer(int length) {
1172 MemberName[] buf = new MemberName[length];
1173 // fill the buffer with dummy structs for the JVM to fill in
1174 for (int i = 0; i < length; i++)
1175 buf[i] = new MemberName();
1176 return buf;
1177 }
1178 }
1179 }
--- EOF ---