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.VerifyAccess;
29
30 import java.lang.reflect.Constructor;
31 import java.lang.reflect.Field;
32 import java.lang.reflect.Member;
33 import java.lang.reflect.Method;
34 import java.lang.reflect.Modifier;
35 import java.util.Objects;
36
37 import static java.lang.invoke.MethodHandleNatives.Constants.*;
38 import static java.lang.invoke.MethodHandleStatics.newIllegalArgumentException;
39 import static java.lang.invoke.MethodHandleStatics.newInternalError;
40
41 /**
42 * A {@code MemberName} is a compact symbolic datum which fully characterizes
43 * a method or field reference.
44 * A member name refers to a field, method, constructor, or member type.
45 * Every member name has a simple name (a string) and a type (either a Class or MethodType).
46 * A member name may also have a non-null declaring class, or it may be simply
47 * a naked name/type pair.
79 private int flags; // modifier bits; see reflect.Modifier
80 private ResolvedMethodName method; // cached resolved method information
81 //@Injected intptr_t vmindex; // vtable index or offset of resolved member
82 Object resolution; // if null, this guy is resolved
83
84 /** Return the declaring class of this member.
85 * In the case of a bare name and type, the declaring class will be null.
86 */
87 public Class<?> getDeclaringClass() {
88 return clazz;
89 }
90
91 /** Utility method producing the class loader of the declaring class. */
92 public ClassLoader getClassLoader() {
93 return clazz.getClassLoader();
94 }
95
96 /** Return the simple name of this member.
97 * For a type, it is the same as {@link Class#getSimpleName}.
98 * For a method or field, it is the simple name of the member.
99 * For a constructor, it is always {@code "<init>"}.
100 */
101 public String getName() {
102 if (name == null) {
103 expandFromVM();
104 if (name == null) {
105 return null;
106 }
107 }
108 return name;
109 }
110
111 public MethodType getMethodOrFieldType() {
112 if (isInvocable())
113 return getMethodType();
114 if (isGetter())
115 return MethodType.methodType(getFieldType());
116 if (isSetter())
117 return MethodType.methodType(void.class, getFieldType());
118 throw new InternalError("not a method or field: "+this);
119 }
169 }
170 if (!isInvocable()) {
171 throw newIllegalArgumentException("not invocable, no method type");
172 }
173
174 // Get a snapshot of type which doesn't get changed by racing threads.
175 final Object type = this.type;
176 if (type instanceof String str) {
177 return str;
178 } else {
179 return getMethodType().toMethodDescriptorString();
180 }
181 }
182
183 /** Return the actual type under which this method or constructor must be invoked.
184 * For non-static methods or constructors, this is the type with a leading parameter,
185 * a reference to declaring class. For static methods, it is the same as the declared type.
186 */
187 public MethodType getInvocationType() {
188 MethodType itype = getMethodOrFieldType();
189 if (isConstructor() && getReferenceKind() == REF_newInvokeSpecial)
190 return itype.changeReturnType(clazz);
191 if (!isStatic())
192 return itype.insertParameterTypes(0, clazz);
193 return itype;
194 }
195
196 /** Return the declared type of this member, which
197 * must be a field or type.
198 * If it is a type member, that type itself is returned.
199 */
200 public Class<?> getFieldType() {
201 if (type == null) {
202 expandFromVM();
203 if (type == null) {
204 return null;
205 }
206 }
207 if (isInvocable()) {
208 throw newIllegalArgumentException("not a field or nested class, no simple type");
209 }
210
211 {
212 // Get a snapshot of type which doesn't get changed by racing threads.
235 }
236
237 /** Return the modifier flags of this member.
238 * @see java.lang.reflect.Modifier
239 */
240 public int getModifiers() {
241 return (flags & RECOGNIZED_MODIFIERS);
242 }
243
244 /** Return the reference kind of this member, or zero if none.
245 */
246 public byte getReferenceKind() {
247 return (byte) ((flags >>> MN_REFERENCE_KIND_SHIFT) & MN_REFERENCE_KIND_MASK);
248 }
249 private boolean referenceKindIsConsistent() {
250 byte refKind = getReferenceKind();
251 if (refKind == REF_NONE) return isType();
252 if (isField()) {
253 assert(staticIsConsistent());
254 assert(MethodHandleNatives.refKindIsField(refKind));
255 } else if (isConstructor()) {
256 assert(refKind == REF_newInvokeSpecial || refKind == REF_invokeSpecial);
257 } else if (isMethod()) {
258 assert(staticIsConsistent());
259 assert(MethodHandleNatives.refKindIsMethod(refKind));
260 if (clazz.isInterface())
261 assert(refKind == REF_invokeInterface ||
262 refKind == REF_invokeStatic ||
263 refKind == REF_invokeSpecial ||
264 refKind == REF_invokeVirtual && isObjectPublicMethod());
265 } else {
266 assert(false);
267 }
268 return true;
269 }
270 private boolean isObjectPublicMethod() {
271 if (clazz == Object.class) return true;
272 MethodType mtype = getMethodType();
273 if (name.equals("toString") && mtype.returnType() == String.class && mtype.parameterCount() == 0)
274 return true;
275 if (name.equals("hashCode") && mtype.returnType() == int.class && mtype.parameterCount() == 0)
375 private static final int MH_INVOKE_MODS = Modifier.NATIVE | Modifier.FINAL | Modifier.PUBLIC;
376
377 /** Utility method to query the modifier flags of this member. */
378 public boolean isStatic() {
379 return Modifier.isStatic(flags);
380 }
381 /** Utility method to query the modifier flags of this member. */
382 public boolean isPublic() {
383 return Modifier.isPublic(flags);
384 }
385 /** Utility method to query the modifier flags of this member. */
386 public boolean isPrivate() {
387 return Modifier.isPrivate(flags);
388 }
389 /** Utility method to query the modifier flags of this member. */
390 public boolean isProtected() {
391 return Modifier.isProtected(flags);
392 }
393 /** Utility method to query the modifier flags of this member. */
394 public boolean isFinal() {
395 return Modifier.isFinal(flags);
396 }
397 /** Utility method to query whether this member or its defining class is final. */
398 public boolean canBeStaticallyBound() {
399 return Modifier.isFinal(flags | clazz.getModifiers());
400 }
401 /** Utility method to query the modifier flags of this member. */
402 public boolean isVolatile() {
403 return Modifier.isVolatile(flags);
404 }
405 /** Utility method to query the modifier flags of this member. */
406 public boolean isAbstract() {
407 return Modifier.isAbstract(flags);
408 }
409 /** Utility method to query the modifier flags of this member. */
410 public boolean isNative() {
411 return Modifier.isNative(flags);
412 }
413 // let the rest (native, volatile, transient, etc.) be tested via Modifier.isFoo
414
415 // unofficial modifier flags, used by HotSpot:
416 static final int BRIDGE = 0x00000040;
417 static final int VARARGS = 0x00000080;
418 static final int SYNTHETIC = 0x00001000;
419 static final int ANNOTATION= 0x00002000;
420 static final int ENUM = 0x00004000;
421 /** Utility method to query the modifier flags of this member; returns false if the member is not a method. */
422 public boolean isBridge() {
423 return allFlagsSet(IS_METHOD | BRIDGE);
424 }
425 /** Utility method to query the modifier flags of this member; returns false if the member is not a method. */
426 public boolean isVarargs() {
427 return allFlagsSet(VARARGS) && isInvocable();
428 }
429 /** Utility method to query the modifier flags of this member; returns false if the member is not a method. */
430 public boolean isSynthetic() {
431 return allFlagsSet(SYNTHETIC);
432 }
433
434 static final String CONSTRUCTOR_NAME = "<init>"; // the ever-popular
435
436 // modifiers exported by the JVM:
437 static final int RECOGNIZED_MODIFIERS = 0xFFFF;
438
439 // private flags, not part of RECOGNIZED_MODIFIERS:
440 static final int
441 IS_METHOD = MN_IS_METHOD, // method (not constructor)
442 IS_CONSTRUCTOR = MN_IS_CONSTRUCTOR, // constructor
443 IS_FIELD = MN_IS_FIELD, // field
444 IS_TYPE = MN_IS_TYPE, // nested type
445 CALLER_SENSITIVE = MN_CALLER_SENSITIVE, // @CallerSensitive annotation detected
446 TRUSTED_FINAL = MN_TRUSTED_FINAL; // trusted final field
447
448 static final int ALL_ACCESS = Modifier.PUBLIC | Modifier.PRIVATE | Modifier.PROTECTED;
449 static final int ALL_KINDS = IS_METHOD | IS_CONSTRUCTOR | IS_FIELD | IS_TYPE;
450 static final int IS_INVOCABLE = IS_METHOD | IS_CONSTRUCTOR;
451
452 /** Utility method to query whether this member is a method or constructor. */
453 public boolean isInvocable() {
454 return anyFlagSet(IS_INVOCABLE);
455 }
456 /** Query whether this member is a method. */
457 public boolean isMethod() {
458 return allFlagsSet(IS_METHOD);
459 }
460 /** Query whether this member is a constructor. */
461 public boolean isConstructor() {
462 return allFlagsSet(IS_CONSTRUCTOR);
463 }
464 /** Query whether this member is a field. */
465 public boolean isField() {
466 return allFlagsSet(IS_FIELD);
467 }
468 /** Query whether this member is a type. */
469 public boolean isType() {
470 return allFlagsSet(IS_TYPE);
471 }
472 /** Utility method to query whether this member is neither public, private, nor protected. */
473 public boolean isPackage() {
474 return !anyFlagSet(ALL_ACCESS);
475 }
476 /** Query whether this member has a CallerSensitive annotation. */
477 public boolean isCallerSensitive() {
478 return allFlagsSet(CALLER_SENSITIVE);
479 }
480 /** Query whether this member is a trusted final field. */
481 public boolean isTrustedFinalField() {
482 return allFlagsSet(TRUSTED_FINAL | IS_FIELD);
483 }
567 throw new AbstractMethodError(this.toString());
568 if (getReferenceKind() == REF_invokeVirtual)
569 changeReferenceKind(REF_invokeSpecial, REF_invokeVirtual);
570 else if (getReferenceKind() == REF_invokeInterface)
571 // invokeSpecial on a default method
572 changeReferenceKind(REF_invokeSpecial, REF_invokeInterface);
573 }
574 }
575 public MemberName asSpecial() {
576 switch (getReferenceKind()) {
577 case REF_invokeSpecial: return this;
578 case REF_invokeVirtual: return clone().changeReferenceKind(REF_invokeSpecial, REF_invokeVirtual);
579 case REF_invokeInterface: return clone().changeReferenceKind(REF_invokeSpecial, REF_invokeInterface);
580 case REF_newInvokeSpecial: return clone().changeReferenceKind(REF_invokeSpecial, REF_newInvokeSpecial);
581 }
582 throw new IllegalArgumentException(this.toString());
583 }
584 /** If this MN is not REF_newInvokeSpecial, return a clone with that ref. kind.
585 * In that case it must already be REF_invokeSpecial.
586 */
587 public MemberName asConstructor() {
588 switch (getReferenceKind()) {
589 case REF_invokeSpecial: return clone().changeReferenceKind(REF_newInvokeSpecial, REF_invokeSpecial);
590 case REF_newInvokeSpecial: return this;
591 }
592 throw new IllegalArgumentException(this.toString());
593 }
594 /** If this MN is a REF_invokeSpecial, return a clone with the "normal" kind
595 * REF_invokeVirtual; also switch either to REF_invokeInterface if clazz.isInterface.
596 * The end result is to get a fully virtualized version of the MN.
597 * (Note that resolving in the JVM will sometimes devirtualize, changing
598 * REF_invokeVirtual of a final to REF_invokeSpecial, and REF_invokeInterface
599 * in some corner cases to either of the previous two; this transform
600 * undoes that change under the assumption that it occurred.)
601 */
602 public MemberName asNormalOriginal() {
603 byte refKind = getReferenceKind();
604 byte newRefKind = switch (refKind) {
605 case REF_invokeInterface,
606 REF_invokeVirtual,
607 REF_invokeSpecial -> clazz.isInterface() ? REF_invokeInterface : REF_invokeVirtual;
608 default -> refKind;
609 };
610 if (newRefKind == refKind)
611 return this;
612 MemberName result = clone().changeReferenceKind(newRefKind, refKind);
613 assert(this.referenceKindIsConsistentWith(result.getReferenceKind()));
614 return result;
615 }
616 /** Create a name for the given reflected constructor. The resulting name will be in a resolved state. */
617 @SuppressWarnings("LeakingThisInConstructor")
618 public MemberName(Constructor<?> ctor) {
619 Objects.requireNonNull(ctor);
620 // fill in vmtarget, vmindex while we have ctor in hand:
621 MethodHandleNatives.init(this, ctor);
622 assert(isResolved() && this.clazz != null);
623 this.name = CONSTRUCTOR_NAME;
624 if (this.type == null)
625 this.type = new Object[] { void.class, ctor.getParameterTypes() };
626 }
627 /** Create a name for the given reflected field. The resulting name will be in a resolved state.
628 */
629 public MemberName(Field fld) {
630 this(fld, false);
631 }
632 static {
633 // the following MemberName constructor relies on these ranges matching up
634 assert((REF_putStatic - REF_getStatic) == (REF_putField - REF_getField));
635 }
636 @SuppressWarnings("LeakingThisInConstructor")
637 public MemberName(Field fld, boolean makeSetter) {
638 Objects.requireNonNull(fld);
639 // fill in vmtarget, vmindex while we have fld in hand:
640 MethodHandleNatives.init(this, fld);
641 assert(isResolved() && this.clazz != null);
642 this.name = fld.getName();
643 this.type = fld.getType();
644 byte refKind = this.getReferenceKind();
645 assert(refKind == (isStatic() ? REF_getStatic : REF_getField));
737 if (this == that) return true;
738 if (that == null) return false;
739 return this.clazz == that.clazz
740 && this.getReferenceKind() == that.getReferenceKind()
741 && Objects.equals(this.name, that.name)
742 && Objects.equals(this.getType(), that.getType());
743 }
744
745 // Construction from symbolic parts, for queries:
746 /** Create a field or type name from the given components:
747 * Declaring class, name, type, reference kind.
748 * The declaring class may be supplied as null if this is to be a bare name and type.
749 * The resulting name will in an unresolved state.
750 */
751 public MemberName(Class<?> defClass, String name, Class<?> type, byte refKind) {
752 init(defClass, name, type, flagsMods(IS_FIELD, 0, refKind));
753 initResolved(false);
754 }
755 /** Create a method or constructor name from the given components:
756 * Declaring class, name, type, reference kind.
757 * It will be a constructor if and only if the name is {@code "<init>"}.
758 * The declaring class may be supplied as null if this is to be a bare name and type.
759 * The last argument is optional, a boolean which requests REF_invokeSpecial.
760 * The resulting name will in an unresolved state.
761 */
762 public MemberName(Class<?> defClass, String name, MethodType type, byte refKind) {
763 int initFlags = (name != null && name.equals(CONSTRUCTOR_NAME) ? IS_CONSTRUCTOR : IS_METHOD);
764 init(defClass, name, type, flagsMods(initFlags, 0, refKind));
765 initResolved(false);
766 }
767 /** Create a method, constructor, or field name from the given components:
768 * Reference kind, declaring class, name, type.
769 */
770 public MemberName(byte refKind, Class<?> defClass, String name, Object type) {
771 int kindFlags;
772 if (MethodHandleNatives.refKindIsField(refKind)) {
773 kindFlags = IS_FIELD;
774 if (!(type instanceof Class))
775 throw newIllegalArgumentException("not a field type");
776 } else if (MethodHandleNatives.refKindIsMethod(refKind)) {
777 kindFlags = IS_METHOD;
778 if (!(type instanceof MethodType))
779 throw newIllegalArgumentException("not a method type");
780 } else if (refKind == REF_newInvokeSpecial) {
781 kindFlags = IS_CONSTRUCTOR;
782 if (!(type instanceof MethodType) ||
783 !CONSTRUCTOR_NAME.equals(name))
784 throw newIllegalArgumentException("not a constructor type or name");
785 } else {
786 throw newIllegalArgumentException("bad reference kind "+refKind);
787 }
788 init(defClass, name, type, flagsMods(kindFlags, 0, refKind));
789 initResolved(false);
790 }
791
792 /** Query whether this member name is resolved.
793 * A resolved member name is one for which the JVM has found
794 * a method, constructor, field, or type binding corresponding exactly to the name.
795 * (Document?)
796 */
797 public boolean isResolved() {
798 return resolution == null;
799 }
800
801 void initResolved(boolean isResolved) {
879 if (from instanceof MethodHandles.Lookup lookup) {
880 from = lookup.lookupClass();
881 m = lookup.lookupClass().getModule();
882 plc = lookup.previousLookupClass();
883 } else {
884 m = ((Class<?>)from).getModule();
885 plc = null;
886 }
887 message += ", from " + from + " (" + m + ")";
888 if (plc != null) {
889 message += ", previous lookup " +
890 plc.getName() + " (" + plc.getModule() + ")";
891 }
892 }
893 }
894 return new IllegalAccessException(message);
895 }
896 private String message() {
897 if (isResolved())
898 return "no access";
899 else if (isConstructor())
900 return "no such constructor";
901 else if (isMethod())
902 return "no such method";
903 else
904 return "no such field";
905 }
906 public ReflectiveOperationException makeAccessException() {
907 String message = message() + ": " + this;
908 ReflectiveOperationException ex;
909 if (isResolved() || !(resolution instanceof NoSuchMethodError ||
910 resolution instanceof NoSuchFieldError))
911 ex = new IllegalAccessException(message);
912 else if (isConstructor())
913 ex = new NoSuchMethodException(message);
914 else if (isMethod())
915 ex = new NoSuchMethodException(message);
916 else
917 ex = new NoSuchFieldException(message);
918 if (resolution instanceof Throwable res)
919 ex.initCause(res);
920 return ex;
921 }
922
923 /** Actually making a query requires an access check. */
924 /*non-public*/
925 static Factory getFactory() {
926 return Factory.INSTANCE;
927 }
928 /** A factory type for resolving member names with the help of the VM.
929 * TBD: Define access-safe public constructors for this factory.
930 */
931 /*non-public*/
932 static class Factory {
|
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 jdk.internal.value.PrimitiveClass;
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.Objects;
37
38 import static java.lang.invoke.MethodHandleNatives.Constants.*;
39 import static java.lang.invoke.MethodHandleStatics.newIllegalArgumentException;
40 import static java.lang.invoke.MethodHandleStatics.newInternalError;
41
42 /**
43 * A {@code MemberName} is a compact symbolic datum which fully characterizes
44 * a method or field reference.
45 * A member name refers to a field, method, constructor, or member type.
46 * Every member name has a simple name (a string) and a type (either a Class or MethodType).
47 * A member name may also have a non-null declaring class, or it may be simply
48 * a naked name/type pair.
80 private int flags; // modifier bits; see reflect.Modifier
81 private ResolvedMethodName method; // cached resolved method information
82 //@Injected intptr_t vmindex; // vtable index or offset of resolved member
83 Object resolution; // if null, this guy is resolved
84
85 /** Return the declaring class of this member.
86 * In the case of a bare name and type, the declaring class will be null.
87 */
88 public Class<?> getDeclaringClass() {
89 return clazz;
90 }
91
92 /** Utility method producing the class loader of the declaring class. */
93 public ClassLoader getClassLoader() {
94 return clazz.getClassLoader();
95 }
96
97 /** Return the simple name of this member.
98 * For a type, it is the same as {@link Class#getSimpleName}.
99 * For a method or field, it is the simple name of the member.
100 * For an identity object constructor, it is {@code "<init>"}.
101 * For a value class static factory method, it is {@code "<vnew>"}.
102 */
103 public String getName() {
104 if (name == null) {
105 expandFromVM();
106 if (name == null) {
107 return null;
108 }
109 }
110 return name;
111 }
112
113 public MethodType getMethodOrFieldType() {
114 if (isInvocable())
115 return getMethodType();
116 if (isGetter())
117 return MethodType.methodType(getFieldType());
118 if (isSetter())
119 return MethodType.methodType(void.class, getFieldType());
120 throw new InternalError("not a method or field: "+this);
121 }
171 }
172 if (!isInvocable()) {
173 throw newIllegalArgumentException("not invocable, no method type");
174 }
175
176 // Get a snapshot of type which doesn't get changed by racing threads.
177 final Object type = this.type;
178 if (type instanceof String str) {
179 return str;
180 } else {
181 return getMethodType().toMethodDescriptorString();
182 }
183 }
184
185 /** Return the actual type under which this method or constructor must be invoked.
186 * For non-static methods or constructors, this is the type with a leading parameter,
187 * a reference to declaring class. For static methods, it is the same as the declared type.
188 */
189 public MethodType getInvocationType() {
190 MethodType itype = getMethodOrFieldType();
191 Class<?> c = PrimitiveClass.isPrimitiveClass(clazz) ? PrimitiveClass.asValueType(clazz) : clazz;
192 if (isObjectConstructor() && getReferenceKind() == REF_newInvokeSpecial)
193 return itype.changeReturnType(c);
194 if (!isStatic())
195 return itype.insertParameterTypes(0, c);
196 return itype;
197 }
198
199 /** Return the declared type of this member, which
200 * must be a field or type.
201 * If it is a type member, that type itself is returned.
202 */
203 public Class<?> getFieldType() {
204 if (type == null) {
205 expandFromVM();
206 if (type == null) {
207 return null;
208 }
209 }
210 if (isInvocable()) {
211 throw newIllegalArgumentException("not a field or nested class, no simple type");
212 }
213
214 {
215 // Get a snapshot of type which doesn't get changed by racing threads.
238 }
239
240 /** Return the modifier flags of this member.
241 * @see java.lang.reflect.Modifier
242 */
243 public int getModifiers() {
244 return (flags & RECOGNIZED_MODIFIERS);
245 }
246
247 /** Return the reference kind of this member, or zero if none.
248 */
249 public byte getReferenceKind() {
250 return (byte) ((flags >>> MN_REFERENCE_KIND_SHIFT) & MN_REFERENCE_KIND_MASK);
251 }
252 private boolean referenceKindIsConsistent() {
253 byte refKind = getReferenceKind();
254 if (refKind == REF_NONE) return isType();
255 if (isField()) {
256 assert(staticIsConsistent());
257 assert(MethodHandleNatives.refKindIsField(refKind));
258 } else if (isObjectConstructor()) {
259 assert(refKind == REF_newInvokeSpecial || refKind == REF_invokeSpecial);
260 } else if (isMethod()) {
261 assert(staticIsConsistent());
262 assert(MethodHandleNatives.refKindIsMethod(refKind));
263 if (clazz.isInterface())
264 assert(refKind == REF_invokeInterface ||
265 refKind == REF_invokeStatic ||
266 refKind == REF_invokeSpecial ||
267 refKind == REF_invokeVirtual && isObjectPublicMethod());
268 } else {
269 assert(false);
270 }
271 return true;
272 }
273 private boolean isObjectPublicMethod() {
274 if (clazz == Object.class) return true;
275 MethodType mtype = getMethodType();
276 if (name.equals("toString") && mtype.returnType() == String.class && mtype.parameterCount() == 0)
277 return true;
278 if (name.equals("hashCode") && mtype.returnType() == int.class && mtype.parameterCount() == 0)
378 private static final int MH_INVOKE_MODS = Modifier.NATIVE | Modifier.FINAL | Modifier.PUBLIC;
379
380 /** Utility method to query the modifier flags of this member. */
381 public boolean isStatic() {
382 return Modifier.isStatic(flags);
383 }
384 /** Utility method to query the modifier flags of this member. */
385 public boolean isPublic() {
386 return Modifier.isPublic(flags);
387 }
388 /** Utility method to query the modifier flags of this member. */
389 public boolean isPrivate() {
390 return Modifier.isPrivate(flags);
391 }
392 /** Utility method to query the modifier flags of this member. */
393 public boolean isProtected() {
394 return Modifier.isProtected(flags);
395 }
396 /** Utility method to query the modifier flags of this member. */
397 public boolean isFinal() {
398 // all fields declared in a value type are effectively final
399 assert(!clazz.isValue() || !isField() || Modifier.isFinal(flags));
400 return Modifier.isFinal(flags);
401 }
402 /** Utility method to query whether this member or its defining class is final. */
403 public boolean canBeStaticallyBound() {
404 return Modifier.isFinal(flags | clazz.getModifiers());
405 }
406 /** Utility method to query the modifier flags of this member. */
407 public boolean isVolatile() {
408 return Modifier.isVolatile(flags);
409 }
410 /** Utility method to query the modifier flags of this member. */
411 public boolean isAbstract() {
412 return Modifier.isAbstract(flags);
413 }
414 /** Utility method to query the modifier flags of this member. */
415 public boolean isNative() {
416 return Modifier.isNative(flags);
417 }
418 // let the rest (native, volatile, transient, etc.) be tested via Modifier.isFoo
419
420 // unofficial modifier flags, used by HotSpot:
421 static final int BRIDGE = 0x00000040;
422 static final int VARARGS = 0x00000080;
423 static final int SYNTHETIC = 0x00001000;
424 static final int ANNOTATION = 0x00002000;
425 static final int ENUM = 0x00004000;
426
427 /** Utility method to query the modifier flags of this member; returns false if the member is not a method. */
428 public boolean isBridge() {
429 return allFlagsSet(IS_METHOD | BRIDGE);
430 }
431 /** Utility method to query the modifier flags of this member; returns false if the member is not a method. */
432 public boolean isVarargs() {
433 return allFlagsSet(VARARGS) && isInvocable();
434 }
435 /** Utility method to query the modifier flags of this member; returns false if the member is not a method. */
436 public boolean isSynthetic() {
437 return allFlagsSet(SYNTHETIC);
438 }
439
440 /** Query whether this member is a flattened field */
441 public boolean isFlattened() { return (flags & MN_FLATTENED) == MN_FLATTENED; }
442
443 /** Query whether this member is a field of a primitive class. */
444 public boolean isInlineableField() {
445 if (isField()) {
446 Class<?> type = getFieldType();
447 return PrimitiveClass.isPrimitiveValueType(type) || (type.isValue() && !PrimitiveClass.isPrimitiveClass(type));
448 }
449 return false;
450 }
451
452 static final String CONSTRUCTOR_NAME = "<init>";
453 static final String VALUE_FACTORY_NAME = "<vnew>"; // the ever-popular
454
455 // modifiers exported by the JVM:
456 static final int RECOGNIZED_MODIFIERS = 0xFFFF;
457
458 // private flags, not part of RECOGNIZED_MODIFIERS:
459 static final int
460 IS_METHOD = MN_IS_METHOD, // method (not object constructor)
461 IS_OBJECT_CONSTRUCTOR = MN_IS_OBJECT_CONSTRUCTOR, // object constructor
462 IS_FIELD = MN_IS_FIELD, // field
463 IS_TYPE = MN_IS_TYPE, // nested type
464 CALLER_SENSITIVE = MN_CALLER_SENSITIVE, // @CallerSensitive annotation detected
465 TRUSTED_FINAL = MN_TRUSTED_FINAL; // trusted final field
466
467 static final int ALL_ACCESS = Modifier.PUBLIC | Modifier.PRIVATE | Modifier.PROTECTED;
468 static final int ALL_KINDS = IS_METHOD | IS_OBJECT_CONSTRUCTOR | IS_FIELD | IS_TYPE;
469 static final int IS_INVOCABLE = IS_METHOD | IS_OBJECT_CONSTRUCTOR;
470
471 /** Utility method to query whether this member is a method or constructor. */
472 public boolean isInvocable() {
473 return anyFlagSet(IS_INVOCABLE);
474 }
475 /** Query whether this member is a method. */
476 public boolean isMethod() {
477 return allFlagsSet(IS_METHOD);
478 }
479 /** Query whether this member is a constructor. */
480 public boolean isObjectConstructor() {
481 return allFlagsSet(IS_OBJECT_CONSTRUCTOR);
482 }
483 /** Query whether this member is an object constructor or static <init> factory */
484 public boolean isStaticValueFactoryMethod() {
485 return VALUE_FACTORY_NAME.equals(name) && isMethod();
486 }
487
488 /** Query whether this member is a field. */
489 public boolean isField() {
490 return allFlagsSet(IS_FIELD);
491 }
492 /** Query whether this member is a type. */
493 public boolean isType() {
494 return allFlagsSet(IS_TYPE);
495 }
496 /** Utility method to query whether this member is neither public, private, nor protected. */
497 public boolean isPackage() {
498 return !anyFlagSet(ALL_ACCESS);
499 }
500 /** Query whether this member has a CallerSensitive annotation. */
501 public boolean isCallerSensitive() {
502 return allFlagsSet(CALLER_SENSITIVE);
503 }
504 /** Query whether this member is a trusted final field. */
505 public boolean isTrustedFinalField() {
506 return allFlagsSet(TRUSTED_FINAL | IS_FIELD);
507 }
591 throw new AbstractMethodError(this.toString());
592 if (getReferenceKind() == REF_invokeVirtual)
593 changeReferenceKind(REF_invokeSpecial, REF_invokeVirtual);
594 else if (getReferenceKind() == REF_invokeInterface)
595 // invokeSpecial on a default method
596 changeReferenceKind(REF_invokeSpecial, REF_invokeInterface);
597 }
598 }
599 public MemberName asSpecial() {
600 switch (getReferenceKind()) {
601 case REF_invokeSpecial: return this;
602 case REF_invokeVirtual: return clone().changeReferenceKind(REF_invokeSpecial, REF_invokeVirtual);
603 case REF_invokeInterface: return clone().changeReferenceKind(REF_invokeSpecial, REF_invokeInterface);
604 case REF_newInvokeSpecial: return clone().changeReferenceKind(REF_invokeSpecial, REF_newInvokeSpecial);
605 }
606 throw new IllegalArgumentException(this.toString());
607 }
608 /** If this MN is not REF_newInvokeSpecial, return a clone with that ref. kind.
609 * In that case it must already be REF_invokeSpecial.
610 */
611 public MemberName asObjectConstructor() {
612 switch (getReferenceKind()) {
613 case REF_invokeSpecial: return clone().changeReferenceKind(REF_newInvokeSpecial, REF_invokeSpecial);
614 case REF_newInvokeSpecial: return this;
615 }
616 throw new IllegalArgumentException(this.toString());
617 }
618 /** If this MN is a REF_invokeSpecial, return a clone with the "normal" kind
619 * REF_invokeVirtual; also switch either to REF_invokeInterface if clazz.isInterface.
620 * The end result is to get a fully virtualized version of the MN.
621 * (Note that resolving in the JVM will sometimes devirtualize, changing
622 * REF_invokeVirtual of a final to REF_invokeSpecial, and REF_invokeInterface
623 * in some corner cases to either of the previous two; this transform
624 * undoes that change under the assumption that it occurred.)
625 */
626 public MemberName asNormalOriginal() {
627 byte refKind = getReferenceKind();
628 byte newRefKind = switch (refKind) {
629 case REF_invokeInterface,
630 REF_invokeVirtual,
631 REF_invokeSpecial -> clazz.isInterface() ? REF_invokeInterface : REF_invokeVirtual;
632 default -> refKind;
633 };
634 if (newRefKind == refKind)
635 return this;
636 MemberName result = clone().changeReferenceKind(newRefKind, refKind);
637 assert(this.referenceKindIsConsistentWith(result.getReferenceKind()));
638 return result;
639 }
640 /** Create a name for the given reflected constructor. The resulting name will be in a resolved state. */
641 @SuppressWarnings("LeakingThisInConstructor")
642 public MemberName(Constructor<?> ctor) {
643 Objects.requireNonNull(ctor);
644 // fill in vmtarget, vmindex while we have ctor in hand:
645 MethodHandleNatives.init(this, ctor);
646 assert(isResolved() && this.clazz != null);
647 this.name = this.clazz.isValue() ? VALUE_FACTORY_NAME : CONSTRUCTOR_NAME;
648 if (this.type == null) {
649 Class<?> rtype = void.class;
650 if (isStatic()) { // a value class static factory, not a true constructor
651 rtype = getDeclaringClass();
652 }
653 this.type = new Object[] { rtype, ctor.getParameterTypes() };
654 }
655 }
656 /** Create a name for the given reflected field. The resulting name will be in a resolved state.
657 */
658 public MemberName(Field fld) {
659 this(fld, false);
660 }
661 static {
662 // the following MemberName constructor relies on these ranges matching up
663 assert((REF_putStatic - REF_getStatic) == (REF_putField - REF_getField));
664 }
665 @SuppressWarnings("LeakingThisInConstructor")
666 public MemberName(Field fld, boolean makeSetter) {
667 Objects.requireNonNull(fld);
668 // fill in vmtarget, vmindex while we have fld in hand:
669 MethodHandleNatives.init(this, fld);
670 assert(isResolved() && this.clazz != null);
671 this.name = fld.getName();
672 this.type = fld.getType();
673 byte refKind = this.getReferenceKind();
674 assert(refKind == (isStatic() ? REF_getStatic : REF_getField));
766 if (this == that) return true;
767 if (that == null) return false;
768 return this.clazz == that.clazz
769 && this.getReferenceKind() == that.getReferenceKind()
770 && Objects.equals(this.name, that.name)
771 && Objects.equals(this.getType(), that.getType());
772 }
773
774 // Construction from symbolic parts, for queries:
775 /** Create a field or type name from the given components:
776 * Declaring class, name, type, reference kind.
777 * The declaring class may be supplied as null if this is to be a bare name and type.
778 * The resulting name will in an unresolved state.
779 */
780 public MemberName(Class<?> defClass, String name, Class<?> type, byte refKind) {
781 init(defClass, name, type, flagsMods(IS_FIELD, 0, refKind));
782 initResolved(false);
783 }
784 /** Create a method or constructor name from the given components:
785 * Declaring class, name, type, reference kind.
786 * It will be an object constructor if and only if the name is {@code "<init>"}.
787 * It will be a value class instance factory method if and only if the name is {@code "<vnew>"}.
788 * The declaring class may be supplied as null if this is to be a bare name and type.
789 * The last argument is optional, a boolean which requests REF_invokeSpecial.
790 * The resulting name will in an unresolved state.
791 */
792 public MemberName(Class<?> defClass, String name, MethodType type, byte refKind) {
793 int initFlags = CONSTRUCTOR_NAME.equals(name) ? IS_OBJECT_CONSTRUCTOR : IS_METHOD;
794 init(defClass, name, type, flagsMods(initFlags, 0, refKind));
795 initResolved(false);
796 }
797 /** Create a method, constructor, or field name from the given components:
798 * Reference kind, declaring class, name, type.
799 */
800 public MemberName(byte refKind, Class<?> defClass, String name, Object type) {
801 int kindFlags;
802 if (MethodHandleNatives.refKindIsField(refKind)) {
803 kindFlags = IS_FIELD;
804 if (!(type instanceof Class))
805 throw newIllegalArgumentException("not a field type");
806 } else if (MethodHandleNatives.refKindIsMethod(refKind)) {
807 kindFlags = IS_METHOD;
808 if (!(type instanceof MethodType))
809 throw newIllegalArgumentException("not a method type");
810 } else if (refKind == REF_newInvokeSpecial) {
811 kindFlags = IS_OBJECT_CONSTRUCTOR;
812 if (!(type instanceof MethodType) ||
813 !CONSTRUCTOR_NAME.equals(name))
814 throw newIllegalArgumentException("not a constructor type or name");
815 } else {
816 throw newIllegalArgumentException("bad reference kind "+refKind);
817 }
818 init(defClass, name, type, flagsMods(kindFlags, 0, refKind));
819 initResolved(false);
820 }
821
822 /** Query whether this member name is resolved.
823 * A resolved member name is one for which the JVM has found
824 * a method, constructor, field, or type binding corresponding exactly to the name.
825 * (Document?)
826 */
827 public boolean isResolved() {
828 return resolution == null;
829 }
830
831 void initResolved(boolean isResolved) {
909 if (from instanceof MethodHandles.Lookup lookup) {
910 from = lookup.lookupClass();
911 m = lookup.lookupClass().getModule();
912 plc = lookup.previousLookupClass();
913 } else {
914 m = ((Class<?>)from).getModule();
915 plc = null;
916 }
917 message += ", from " + from + " (" + m + ")";
918 if (plc != null) {
919 message += ", previous lookup " +
920 plc.getName() + " (" + plc.getModule() + ")";
921 }
922 }
923 }
924 return new IllegalAccessException(message);
925 }
926 private String message() {
927 if (isResolved())
928 return "no access";
929 else if (isObjectConstructor())
930 return "no such constructor";
931 else if (isMethod())
932 return "no such method";
933 else
934 return "no such field";
935 }
936 public ReflectiveOperationException makeAccessException() {
937 String message = message() + ": " + this;
938 ReflectiveOperationException ex;
939 if (isResolved() || !(resolution instanceof NoSuchMethodError ||
940 resolution instanceof NoSuchFieldError))
941 ex = new IllegalAccessException(message);
942 else if (isObjectConstructor())
943 ex = new NoSuchMethodException(message);
944 else if (isMethod())
945 ex = new NoSuchMethodException(message);
946 else
947 ex = new NoSuchFieldException(message);
948 if (resolution instanceof Throwable res)
949 ex.initCause(res);
950 return ex;
951 }
952
953 /** Actually making a query requires an access check. */
954 /*non-public*/
955 static Factory getFactory() {
956 return Factory.INSTANCE;
957 }
958 /** A factory type for resolving member names with the help of the VM.
959 * TBD: Define access-safe public constructors for this factory.
960 */
961 /*non-public*/
962 static class Factory {
|