1 /*
2 * Copyright (c) 2008, 2013, 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.Method;
34 import java.lang.reflect.Member;
35 import java.lang.reflect.Modifier;
36 import java.util.ArrayList;
37 import java.util.Arrays;
38 import java.util.Collections;
39 import java.util.Iterator;
40 import java.util.List;
41 import static java.lang.invoke.MethodHandleNatives.Constants.*;
42 import static java.lang.invoke.MethodHandleStatics.*;
43 import java.util.Objects;
44
45 /**
46 * A {@code MemberName} is a compact symbolic datum which fully characterizes
47 * a method or field reference.
48 * A member name refers to a field, method, constructor, or member type.
49 * Every member name has a simple name (a string) and a type (either a Class or MethodType).
50 * A member name may also have a non-null declaring class, or it may be simply
51 * a naked name/type pair.
52 * A member name may also have non-zero modifier flags.
53 * Finally, a member name may be either resolved or unresolved.
54 * If it is resolved, the existence of the named
55 * <p>
56 * Whether resolved or not, a member name provides no access rights or
57 * invocation capability to its possessor. It is merely a compact
58 * representation of all symbolic information necessary to link to
59 * and properly use the named member.
60 * <p>
61 * When resolved, a member name's internal implementation may include references to JVM metadata.
62 * This representation is stateless and only descriptive.
63 * It provides no private information and no capability to use the member.
64 * <p>
65 * By contrast, a {@linkplain java.lang.reflect.Method} contains fuller information
66 * about the internals of a method (except its bytecodes) and also
67 * allows invocation. A MemberName is much lighter than a Method,
68 * since it contains about 7 fields to the 16 of Method (plus its sub-arrays),
69 * and those seven fields omit much of the information in Method.
70 * @author jrose
71 */
72 /*non-public*/ final class MemberName implements Member, Cloneable {
73 private Class<?> clazz; // class in which the method is defined
74 private String name; // may be null if not yet materialized
75 private Object type; // may be null if not yet materialized
76 private int flags; // modifier bits; see reflect.Modifier
77 //@Injected JVM_Method* vmtarget;
78 //@Injected int vmindex;
79 private Object resolution; // if null, this guy is resolved
80
81 /** Return the declaring class of this member.
82 * In the case of a bare name and type, the declaring class will be null.
83 */
84 public Class<?> getDeclaringClass() {
85 return clazz;
86 }
87
88 /** Utility method producing the class loader of the declaring class. */
89 public ClassLoader getClassLoader() {
90 return clazz.getClassLoader();
91 }
92
93 /** Return the simple name of this member.
94 * For a type, it is the same as {@link Class#getSimpleName}.
95 * For a method or field, it is the simple name of the member.
96 * For a constructor, it is always {@code "<init>"}.
97 */
98 public String getName() {
99 if (name == null) {
100 expandFromVM();
101 if (name == null) {
102 return null;
103 }
104 }
105 return name;
106 }
107
108 public MethodType getMethodOrFieldType() {
109 if (isInvocable())
110 return getMethodType();
111 if (isGetter())
112 return MethodType.methodType(getFieldType());
113 if (isSetter())
114 return MethodType.methodType(void.class, getFieldType());
115 throw new InternalError("not a method or field: "+this);
116 }
117
223
224 /** Utility method to produce the signature of this member,
225 * used within the class file format to describe its type.
226 */
227 public String getSignature() {
228 if (type == null) {
229 expandFromVM();
230 if (type == null) {
231 return null;
232 }
233 }
234 if (isInvocable())
235 return BytecodeDescriptor.unparse(getMethodType());
236 else
237 return BytecodeDescriptor.unparse(getFieldType());
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 (isConstructor()) {
259 assert(refKind == REF_newInvokeSpecial || refKind == REF_invokeSpecial);
260 } else if (isMethod()) {
261 assert(staticIsConsistent());
262 assert(MethodHandleNatives.refKindIsMethod(refKind));
400 public boolean isNative() {
401 return Modifier.isNative(flags);
402 }
403 // let the rest (native, volatile, transient, etc.) be tested via Modifier.isFoo
404
405 // unofficial modifier flags, used by HotSpot:
406 static final int BRIDGE = 0x00000040;
407 static final int VARARGS = 0x00000080;
408 static final int SYNTHETIC = 0x00001000;
409 static final int ANNOTATION= 0x00002000;
410 static final int ENUM = 0x00004000;
411 /** Utility method to query the modifier flags of this member; returns false if the member is not a method. */
412 public boolean isBridge() {
413 return testAllFlags(IS_METHOD | BRIDGE);
414 }
415 /** Utility method to query the modifier flags of this member; returns false if the member is not a method. */
416 public boolean isVarargs() {
417 return testAllFlags(VARARGS) && isInvocable();
418 }
419 /** Utility method to query the modifier flags of this member; returns false if the member is not a method. */
420 public boolean isSynthetic() {
421 return testAllFlags(SYNTHETIC);
422 }
423
424 static final String CONSTRUCTOR_NAME = "<init>"; // the ever-popular
425
426 // modifiers exported by the JVM:
427 static final int RECOGNIZED_MODIFIERS = 0xFFFF;
428
429 // private flags, not part of RECOGNIZED_MODIFIERS:
430 static final int
431 IS_METHOD = MN_IS_METHOD, // method (not constructor)
432 IS_CONSTRUCTOR = MN_IS_CONSTRUCTOR, // constructor
433 IS_FIELD = MN_IS_FIELD, // field
434 IS_TYPE = MN_IS_TYPE, // nested type
435 CALLER_SENSITIVE = MN_CALLER_SENSITIVE; // @CallerSensitive annotation detected
436
437 static final int ALL_ACCESS = Modifier.PUBLIC | Modifier.PRIVATE | Modifier.PROTECTED;
438 static final int ALL_KINDS = IS_METHOD | IS_CONSTRUCTOR | IS_FIELD | IS_TYPE;
439 static final int IS_INVOCABLE = IS_METHOD | IS_CONSTRUCTOR;
462 }
463 /** Query whether this member is a type. */
464 public boolean isType() {
465 return testAllFlags(IS_TYPE);
466 }
467 /** Utility method to query whether this member is neither public, private, nor protected. */
468 public boolean isPackage() {
469 return !testAnyFlags(ALL_ACCESS);
470 }
471 /** Query whether this member has a CallerSensitive annotation. */
472 public boolean isCallerSensitive() {
473 return testAllFlags(CALLER_SENSITIVE);
474 }
475
476 /** Utility method to query whether this member is accessible from a given lookup class. */
477 public boolean isAccessibleFrom(Class<?> lookupClass) {
478 return VerifyAccess.isMemberAccessible(this.getDeclaringClass(), this.getDeclaringClass(), flags,
479 lookupClass, ALL_ACCESS|MethodHandles.Lookup.PACKAGE);
480 }
481
482 /** Initialize a query. It is not resolved. */
483 private void init(Class<?> defClass, String name, Object type, int flags) {
484 // defining class is allowed to be null (for a naked name/type pair)
485 //name.toString(); // null check
486 //type.equals(type); // null check
487 // fill in fields:
488 this.clazz = defClass;
489 this.name = name;
490 this.type = type;
491 this.flags = flags;
492 assert(testAnyFlags(ALL_KINDS));
493 assert(this.resolution == null); // nobody should have touched this yet
494 //assert(referenceKindIsConsistent()); // do this after resolution
495 }
496
497 /**
498 * Calls down to the VM to fill in the fields. This method is
499 * synchronized to avoid racing calls.
500 */
501 private void expandFromVM() {
502 if (type != null) {
503 return;
504 }
505 if (!isResolved()) {
506 return;
507 }
508 MethodHandleNatives.expand(this);
509 }
510
511 // Capturing information from the Core Reflection API:
512 private static int flagsMods(int flags, int mods, byte refKind) {
513 assert((flags & RECOGNIZED_MODIFIERS) == 0);
514 assert((mods & ~RECOGNIZED_MODIFIERS) == 0);
515 assert((refKind & ~MN_REFERENCE_KIND_MASK) == 0);
516 return flags | mods | (refKind << MN_REFERENCE_KIND_SHIFT);
517 }
518 /** Create a name for the given reflected method. The resulting name will be in a resolved state. */
519 public MemberName(Method m) {
520 this(m, false);
521 }
522 @SuppressWarnings("LeakingThisInConstructor")
523 public MemberName(Method m, boolean wantSpecial) {
524 m.getClass(); // NPE check
525 // fill in vmtarget, vmindex while we have m in hand:
526 MethodHandleNatives.init(this, m);
527 if (clazz == null) { // MHN.init failed
528 if (m.getDeclaringClass() == MethodHandle.class &&
529 isMethodHandleInvokeName(m.getName())) {
530 // The JVM did not reify this signature-polymorphic instance.
531 // Need a special case here.
532 // See comments on MethodHandleNatives.linkMethod.
533 MethodType type = MethodType.methodType(m.getReturnType(), m.getParameterTypes());
534 int flags = flagsMods(IS_METHOD, m.getModifiers(), REF_invokeVirtual);
535 init(MethodHandle.class, m.getName(), type, flags);
536 if (isMethodHandleInvoke())
537 return;
538 }
539 throw new LinkageError(m.toString());
540 }
541 assert(isResolved() && this.clazz != null);
542 this.name = m.getName();
543 if (this.type == null)
544 this.type = new Object[] { m.getReturnType(), m.getParameterTypes() };
545 if (wantSpecial) {
546 if (isAbstract())
547 throw new AbstractMethodError(this.toString());
548 if (getReferenceKind() == REF_invokeVirtual)
549 changeReferenceKind(REF_invokeSpecial, REF_invokeVirtual);
550 else if (getReferenceKind() == REF_invokeInterface)
551 // invokeSpecial on a default method
552 changeReferenceKind(REF_invokeSpecial, REF_invokeInterface);
553 }
554 }
555 public MemberName asSpecial() {
556 switch (getReferenceKind()) {
557 case REF_invokeSpecial: return this;
558 case REF_invokeVirtual: return clone().changeReferenceKind(REF_invokeSpecial, REF_invokeVirtual);
559 case REF_invokeInterface: return clone().changeReferenceKind(REF_invokeSpecial, REF_invokeInterface);
560 case REF_newInvokeSpecial: return clone().changeReferenceKind(REF_invokeSpecial, REF_newInvokeSpecial);
561 }
562 throw new IllegalArgumentException(this.toString());
563 }
564 /** If this MN is not REF_newInvokeSpecial, return a clone with that ref. kind.
565 * In that case it must already be REF_invokeSpecial.
566 */
567 public MemberName asConstructor() {
568 switch (getReferenceKind()) {
569 case REF_invokeSpecial: return clone().changeReferenceKind(REF_newInvokeSpecial, REF_invokeSpecial);
570 case REF_newInvokeSpecial: return this;
571 }
572 throw new IllegalArgumentException(this.toString());
573 }
574 /** If this MN is a REF_invokeSpecial, return a clone with the "normal" kind
575 * REF_invokeVirtual; also switch either to REF_invokeInterface if clazz.isInterface.
576 * The end result is to get a fully virtualized version of the MN.
577 * (Note that resolving in the JVM will sometimes devirtualize, changing
578 * REF_invokeVirtual of a final to REF_invokeSpecial, and REF_invokeInterface
579 * in some corner cases to either of the previous two; this transform
580 * undoes that change under the assumption that it occurred.)
581 */
582 public MemberName asNormalOriginal() {
583 byte normalVirtual = clazz.isInterface() ? REF_invokeInterface : REF_invokeVirtual;
584 byte refKind = getReferenceKind();
585 byte newRefKind = refKind;
586 MemberName result = this;
587 switch (refKind) {
588 case REF_invokeInterface:
589 case REF_invokeVirtual:
590 case REF_invokeSpecial:
591 newRefKind = normalVirtual;
592 break;
593 }
594 if (newRefKind == refKind)
595 return this;
596 result = clone().changeReferenceKind(newRefKind, refKind);
597 assert(this.referenceKindIsConsistentWith(result.getReferenceKind()));
598 return result;
599 }
600 /** Create a name for the given reflected constructor. The resulting name will be in a resolved state. */
601 @SuppressWarnings("LeakingThisInConstructor")
602 public MemberName(Constructor<?> ctor) {
603 ctor.getClass(); // NPE check
604 // fill in vmtarget, vmindex while we have ctor in hand:
605 MethodHandleNatives.init(this, ctor);
606 assert(isResolved() && this.clazz != null);
607 this.name = CONSTRUCTOR_NAME;
608 if (this.type == null)
609 this.type = new Object[] { void.class, ctor.getParameterTypes() };
610 }
611 /** Create a name for the given reflected field. The resulting name will be in a resolved state.
612 */
613 public MemberName(Field fld) {
614 this(fld, false);
615 }
616 @SuppressWarnings("LeakingThisInConstructor")
617 public MemberName(Field fld, boolean makeSetter) {
618 fld.getClass(); // NPE check
619 // fill in vmtarget, vmindex while we have fld in hand:
620 MethodHandleNatives.init(this, fld);
621 assert(isResolved() && this.clazz != null);
622 this.name = fld.getName();
623 this.type = fld.getType();
624 assert((REF_putStatic - REF_getStatic) == (REF_putField - REF_getField));
625 byte refKind = this.getReferenceKind();
626 assert(refKind == (isStatic() ? REF_getStatic : REF_getField));
627 if (makeSetter) {
628 changeReferenceKind((byte)(refKind + (REF_putStatic - REF_getStatic)), refKind);
629 }
630 }
631 public boolean isGetter() {
632 return MethodHandleNatives.refKindIsGetter(getReferenceKind());
633 }
634 public boolean isSetter() {
635 return MethodHandleNatives.refKindIsSetter(getReferenceKind());
636 }
637 public MemberName asSetter() {
638 byte refKind = getReferenceKind();
639 assert(MethodHandleNatives.refKindIsGetter(refKind));
640 assert((REF_putStatic - REF_getStatic) == (REF_putField - REF_getField));
641 byte setterRefKind = (byte)(refKind + (REF_putField - REF_getField));
642 return clone().changeReferenceKind(setterRefKind, refKind);
643 }
644 /** Create a name for the given class. The resulting name will be in a resolved state. */
645 public MemberName(Class<?> type) {
646 init(type.getDeclaringClass(), type.getSimpleName(), type,
647 flagsMods(IS_TYPE, type.getModifiers(), REF_NONE));
648 initResolved(true);
649 }
650
651 /**
652 * Create a name for a signature-polymorphic invoker.
653 * This is a placeholder for a signature-polymorphic instance
654 * (of MH.invokeExact, etc.) that the JVM does not reify.
655 * See comments on {@link MethodHandleNatives#linkMethod}.
656 */
657 static MemberName makeMethodHandleInvoke(String name, MethodType type) {
658 return makeMethodHandleInvoke(name, type, MH_INVOKE_MODS | SYNTHETIC);
659 }
660 static MemberName makeMethodHandleInvoke(String name, MethodType type, int mods) {
661 MemberName mem = new MemberName(MethodHandle.class, name, type, REF_invokeVirtual);
662 mem.flags |= mods; // it's not resolved, but add these modifiers anyway
663 assert(mem.isMethodHandleInvoke()) : mem;
664 return mem;
665 }
666
667 // bare-bones constructor; the JVM will fill it in
668 MemberName() { }
669
670 // locally useful cloner
671 @Override protected MemberName clone() {
672 try {
673 return (MemberName) super.clone();
674 } catch (CloneNotSupportedException ex) {
675 throw newInternalError(ex);
676 }
677 }
678
679 /** Get the definition of this member name.
680 * This may be in a super-class of the declaring class of this member.
681 */
682 public MemberName getDefinition() {
683 if (!isResolved()) throw new IllegalStateException("must be resolved: "+this);
684 if (isType()) return this;
685 MemberName res = this.clone();
686 res.clazz = null;
687 res.type = null;
688 res.name = null;
689 res.resolution = res;
698 }
699 @Override
700 public boolean equals(Object that) {
701 return (that instanceof MemberName && this.equals((MemberName)that));
702 }
703
704 /** Decide if two member names have exactly the same symbolic content.
705 * Does not take into account any actual class members, so even if
706 * two member names resolve to the same actual member, they may
707 * be distinct references.
708 */
709 public boolean equals(MemberName that) {
710 if (this == that) return true;
711 if (that == null) return false;
712 return this.clazz == that.clazz
713 && this.getReferenceKind() == that.getReferenceKind()
714 && Objects.equals(this.name, that.name)
715 && Objects.equals(this.getType(), that.getType());
716 }
717
718 // Construction from symbolic parts, for queries:
719 /** Create a field or type name from the given components:
720 * Declaring class, name, type, reference kind.
721 * The declaring class may be supplied as null if this is to be a bare name and type.
722 * The resulting name will in an unresolved state.
723 */
724 public MemberName(Class<?> defClass, String name, Class<?> type, byte refKind) {
725 init(defClass, name, type, flagsMods(IS_FIELD, 0, refKind));
726 initResolved(false);
727 }
728 /** Create a method or constructor name from the given components:
729 * Declaring class, name, type, reference kind.
730 * It will be a constructor if and only if the name is {@code "<init>"}.
731 * The declaring class may be supplied as null if this is to be a bare name and type.
732 * The last argument is optional, a boolean which requests REF_invokeSpecial.
733 * The resulting name will in an unresolved state.
734 */
735 public MemberName(Class<?> defClass, String name, MethodType type, byte refKind) {
736 int initFlags = (name != null && name.equals(CONSTRUCTOR_NAME) ? IS_CONSTRUCTOR : IS_METHOD);
737 init(defClass, name, type, flagsMods(initFlags, 0, refKind));
738 initResolved(false);
739 }
740 /** Create a method, constructor, or field name from the given components:
741 * Reference kind, declaring class, name, type.
742 */
743 public MemberName(byte refKind, Class<?> defClass, String name, Object type) {
744 int kindFlags;
745 if (MethodHandleNatives.refKindIsField(refKind)) {
746 kindFlags = IS_FIELD;
747 if (!(type instanceof Class))
748 throw newIllegalArgumentException("not a field type");
749 } else if (MethodHandleNatives.refKindIsMethod(refKind)) {
750 kindFlags = IS_METHOD;
751 if (!(type instanceof MethodType))
752 throw newIllegalArgumentException("not a method type");
753 } else if (refKind == REF_newInvokeSpecial) {
754 kindFlags = IS_CONSTRUCTOR;
755 if (!(type instanceof MethodType) ||
756 !CONSTRUCTOR_NAME.equals(name))
757 throw newIllegalArgumentException("not a constructor type or name");
758 } else {
759 throw newIllegalArgumentException("bad reference kind "+refKind);
760 }
761 init(defClass, name, type, flagsMods(kindFlags, 0, refKind));
762 initResolved(false);
763 }
764 /** Query whether this member name is resolved to a non-static, non-final method.
765 */
766 public boolean hasReceiverTypeDispatch() {
767 return MethodHandleNatives.refKindDoesDispatch(getReferenceKind());
768 }
769
770 /** Query whether this member name is resolved.
771 * A resolved member name is one for which the JVM has found
772 * a method, constructor, field, or type binding corresponding exactly to the name.
773 * (Document?)
774 */
775 public boolean isResolved() {
776 return resolution == null;
777 }
778
779 private void initResolved(boolean isResolved) {
780 assert(this.resolution == null); // not initialized yet!
781 if (!isResolved)
782 this.resolution = this;
783 assert(isResolved() == isResolved);
784 }
785
786 void checkForTypeAlias() {
787 if (isInvocable()) {
788 MethodType type;
789 if (this.type instanceof MethodType)
790 type = (MethodType) this.type;
791 else
792 this.type = type = getMethodType();
793 if (type.erase() == type) return;
794 if (VerifyAccess.isTypeVisible(type, clazz)) return;
795 throw new LinkageError("bad method type alias: "+type+" not visible from "+clazz);
796 } else {
797 Class<?> type;
798 if (this.type instanceof Class<?>)
799 type = (Class<?>) this.type;
800 else
801 this.type = type = getFieldType();
802 if (VerifyAccess.isTypeVisible(type, clazz)) return;
803 throw new LinkageError("bad field type alias: "+type+" not visible from "+clazz);
804 }
805 }
872 else if (isMethod())
873 ex = new NoSuchMethodException(message);
874 else
875 ex = new NoSuchFieldException(message);
876 if (resolution instanceof Throwable)
877 ex.initCause((Throwable) resolution);
878 return ex;
879 }
880
881 /** Actually making a query requires an access check. */
882 /*non-public*/ static Factory getFactory() {
883 return Factory.INSTANCE;
884 }
885 /** A factory type for resolving member names with the help of the VM.
886 * TBD: Define access-safe public constructors for this factory.
887 */
888 /*non-public*/ static class Factory {
889 private Factory() { } // singleton pattern
890 static Factory INSTANCE = new Factory();
891
892 private static int ALLOWED_FLAGS = ALL_KINDS;
893
894 /// Queries
895 List<MemberName> getMembers(Class<?> defc,
896 String matchName, Object matchType,
897 int matchFlags, Class<?> lookupClass) {
898 matchFlags &= ALLOWED_FLAGS;
899 String matchSig = null;
900 if (matchType != null) {
901 matchSig = BytecodeDescriptor.unparse(matchType);
902 if (matchSig.startsWith("("))
903 matchFlags &= ~(ALL_KINDS & ~IS_INVOCABLE);
904 else
905 matchFlags &= ~(ALL_KINDS & ~IS_FIELD);
906 }
907 final int BUF_MAX = 0x2000;
908 int len1 = matchName == null ? 10 : matchType == null ? 4 : 1;
909 MemberName[] buf = newMemberBuffer(len1);
910 int totalCount = 0;
911 ArrayList<MemberName[]> bufs = null;
912 int bufCount = 0;
938 }
939 result.addAll(Arrays.asList(buf).subList(0, bufCount));
940 // Signature matching is not the same as type matching, since
941 // one signature might correspond to several types.
942 // So if matchType is a Class or MethodType, refilter the results.
943 if (matchType != null && matchType != matchSig) {
944 for (Iterator<MemberName> it = result.iterator(); it.hasNext();) {
945 MemberName m = it.next();
946 if (!matchType.equals(m.getType()))
947 it.remove();
948 }
949 }
950 return result;
951 }
952 /** Produce a resolved version of the given member.
953 * Super types are searched (for inherited members) if {@code searchSupers} is true.
954 * Access checking is performed on behalf of the given {@code lookupClass}.
955 * If lookup fails or access is not permitted, null is returned.
956 * Otherwise a fresh copy of the given member is returned, with modifier bits filled in.
957 */
958 private MemberName resolve(byte refKind, MemberName ref, Class<?> lookupClass) {
959 MemberName m = ref.clone(); // JVM will side-effect the ref
960 assert(refKind == m.getReferenceKind());
961 try {
962 m = MethodHandleNatives.resolve(m, lookupClass);
963 m.checkForTypeAlias();
964 m.resolution = null;
965 } catch (LinkageError ex) {
966 // JVM reports that the "bytecode behavior" would get an error
967 assert(!m.isResolved());
968 m.resolution = ex;
969 return m;
970 }
971 assert(m.referenceKindIsConsistent());
972 m.initResolved(true);
973 assert(m.vminfoIsConsistent());
974 return m;
975 }
976 /** Produce a resolved version of the given member.
977 * Super types are searched (for inherited members) if {@code searchSupers} is true.
978 * Access checking is performed on behalf of the given {@code lookupClass}.
979 * If lookup fails or access is not permitted, a {@linkplain ReflectiveOperationException} is thrown.
980 * Otherwise a fresh copy of the given member is returned, with modifier bits filled in.
981 */
982 public
983 <NoSuchMemberException extends ReflectiveOperationException>
984 MemberName resolveOrFail(byte refKind, MemberName m, Class<?> lookupClass,
985 Class<NoSuchMemberException> nsmClass)
986 throws IllegalAccessException, NoSuchMemberException {
987 MemberName result = resolve(refKind, m, lookupClass);
988 if (result.isResolved())
989 return result;
990 ReflectiveOperationException ex = result.makeAccessException();
991 if (ex instanceof IllegalAccessException) throw (IllegalAccessException) ex;
992 throw nsmClass.cast(ex);
993 }
994 /** Produce a resolved version of the given member.
995 * Super types are searched (for inherited members) if {@code searchSupers} is true.
996 * Access checking is performed on behalf of the given {@code lookupClass}.
997 * If lookup fails or access is not permitted, return null.
998 * Otherwise a fresh copy of the given member is returned, with modifier bits filled in.
999 */
1000 public
1001 MemberName resolveOrNull(byte refKind, MemberName m, Class<?> lookupClass) {
1002 MemberName result = resolve(refKind, m, lookupClass);
1003 if (result.isResolved())
1004 return result;
1005 return null;
1006 }
1007 /** Return a list of all methods defined by the given class.
1008 * Super types are searched (for inherited members) if {@code searchSupers} is true.
1009 * Access checking is performed on behalf of the given {@code lookupClass}.
1010 * Inaccessible members are not added to the last.
1011 */
1012 public List<MemberName> getMethods(Class<?> defc, boolean searchSupers,
1013 Class<?> lookupClass) {
1014 return getMethods(defc, searchSupers, null, null, lookupClass);
1015 }
1016 /** Return a list of matching methods defined by the given class.
1017 * Super types are searched (for inherited members) if {@code searchSupers} is true.
1018 * Returned methods will match the name (if not null) and the type (if not null).
1019 * Access checking is performed on behalf of the given {@code lookupClass}.
1020 * Inaccessible members are not added to the last.
1021 */
1022 public List<MemberName> getMethods(Class<?> defc, boolean searchSupers,
1023 String name, MethodType type, Class<?> lookupClass) {
1024 int matchFlags = IS_METHOD | (searchSupers ? SEARCH_ALL_SUPERS : 0);
1025 return getMembers(defc, name, type, matchFlags, lookupClass);
1026 }
1052 return getMembers(defc, name, type, matchFlags, lookupClass);
1053 }
1054 /** Return a list of all nested types defined by the given class.
1055 * Super types are searched (for inherited members) if {@code searchSupers} is true.
1056 * Access checking is performed on behalf of the given {@code lookupClass}.
1057 * Inaccessible members are not added to the last.
1058 */
1059 public List<MemberName> getNestedTypes(Class<?> defc, boolean searchSupers,
1060 Class<?> lookupClass) {
1061 int matchFlags = IS_TYPE | (searchSupers ? SEARCH_ALL_SUPERS : 0);
1062 return getMembers(defc, null, null, matchFlags, lookupClass);
1063 }
1064 private static MemberName[] newMemberBuffer(int length) {
1065 MemberName[] buf = new MemberName[length];
1066 // fill the buffer with dummy structs for the JVM to fill in
1067 for (int i = 0; i < length; i++)
1068 buf[i] = new MemberName();
1069 return buf;
1070 }
1071 }
1072
1073 // static {
1074 // System.out.println("Hello world! My methods are:");
1075 // System.out.println(Factory.INSTANCE.getMethods(MemberName.class, true, null));
1076 // }
1077 }
|
1 /*
2 * Copyright (c) 2008, 2014, 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.Method;
34 import java.lang.reflect.Member;
35 import java.lang.reflect.Modifier;
36 import java.util.ArrayList;
37 import java.util.Arrays;
38 import java.util.Collections;
39 import java.util.Iterator;
40 import java.util.List;
41
42 import static java.lang.invoke.MethodHandleNatives.Constants.*;
43 import static java.lang.invoke.MethodHandleStatics.*;
44
45 import sun.misc.JavaLangAccess;
46 import sun.misc.SharedSecrets;
47
48 import java.util.Objects;
49
50 /**
51 * A {@code MemberName} is a compact symbolic datum which fully characterizes
52 * a method or field reference.
53 * A member name refers to a field, method, constructor, or member type.
54 * Every member name has a simple name (a string) and a type (either a Class or MethodType).
55 * A member name may also have a non-null declaring class, or it may be simply
56 * a naked name/type pair.
57 * A member name may also have non-zero modifier flags.
58 * Finally, a member name may be either resolved or unresolved.
59 * If it is resolved, the existence of the named
60 * <p>
61 * Whether resolved or not, a member name provides no access rights or
62 * invocation capability to its possessor. It is merely a compact
63 * representation of all symbolic information necessary to link to
64 * and properly use the named member.
65 * <p>
66 * When resolved, a member name's internal implementation may include references to JVM metadata.
67 * This representation is stateless and only descriptive.
68 * It provides no private information and no capability to use the member.
69 * <p>
70 * By contrast, a {@linkplain java.lang.reflect.Method} contains fuller information
71 * about the internals of a method (except its bytecodes) and also
72 * allows invocation. A MemberName is much lighter than a Method,
73 * since it contains about 7 fields to the 16 of Method (plus its sub-arrays),
74 * and those seven fields omit much of the information in Method.
75 * @author jrose
76 */
77 @SuppressWarnings("rawtypes") //Comparable in next line
78 /*non-public*/ final class MemberName implements Member, Comparable, Cloneable {
79 private Class<?> clazz; // class in which the method 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 //@Injected JVM_Method* vmtarget;
84 //@Injected int vmindex;
85 private Object resolution; // if null, this guy is resolved
86
87 private static final JavaLangAccess jla = SharedSecrets.getJavaLangAccess();
88
89 // bare-bones constructor; the JVM will fill it in
90 MemberName() { }
91
92 /** Create a name for the given class. The resulting name will be in a resolved state. */
93 public MemberName(Class<?> type) {
94 init(type.getDeclaringClass(), type.getSimpleName(), type,
95 flagsMods(IS_TYPE, type.getModifiers(), REF_NONE));
96 initResolved(true);
97 }
98
99 // Construction from symbolic parts, for queries:
100 /** Create a field or type name from the given components:
101 * Declaring class, name, type, reference kind.
102 * The declaring class may be supplied as null if this is to be a bare name and type.
103 * The resulting name will in an unresolved state.
104 */
105 public MemberName(Class<?> defClass, String name, Class<?> type, byte refKind) {
106 init(defClass, name, type, flagsMods(IS_FIELD, 0, refKind));
107 initResolved(false);
108 }
109
110 /** Create a field or type name from the given components: Declaring class, name, type.
111 * The declaring class may be supplied as null if this is to be a bare name and type.
112 * The modifier flags default to zero.
113 * The resulting name will in an unresolved state.
114 */
115 public MemberName(Class<?> defClass, String name, Class<?> type, Void unused) {
116 this(defClass, name, type, REF_NONE);
117 initResolved(false);
118 }
119
120 /** Create a method or constructor name from the given components: Declaring class, name, type, modifiers.
121 * It will be a constructor if and only if the name is {@code "<init>"}.
122 * The declaring class may be supplied as null if this is to be a bare name and type.
123 * The last argument is optional, a boolean which requests REF_invokeSpecial.
124 * The resulting name will in an unresolved state.
125 */
126 public MemberName(Class<?> defClass, String name, MethodType type, byte refKind) {
127 int initFlags = (name != null && name.equals(CONSTRUCTOR_NAME) ? IS_CONSTRUCTOR : IS_METHOD);
128 init(defClass, name, type, flagsMods(initFlags, 0, refKind));
129 initResolved(false);
130 }
131
132 /** Create a method, constructor, or field name from the given components:
133 * Reference kind, declaring class, name, type.
134 */
135 public MemberName(byte refKind, Class<?> defClass, String name, Object type) {
136 int kindFlags;
137 if (MethodHandleNatives.refKindIsField(refKind)) {
138 kindFlags = IS_FIELD;
139 if (!(type instanceof Class))
140 throw newIllegalArgumentException("not a field type");
141 } else if (MethodHandleNatives.refKindIsMethod(refKind)) {
142 kindFlags = IS_METHOD;
143 if (!(type instanceof MethodType))
144 throw newIllegalArgumentException("not a method type");
145 } else if (refKind == REF_newInvokeSpecial) {
146 kindFlags = IS_CONSTRUCTOR;
147 if (!(type instanceof MethodType) ||
148 !CONSTRUCTOR_NAME.equals(name))
149 throw newIllegalArgumentException("not a constructor type or name");
150 } else {
151 throw newIllegalArgumentException("bad reference kind "+refKind);
152 }
153 init(defClass, name, type, flagsMods(kindFlags, 0, refKind));
154 initResolved(false);
155 }
156
157 /** Create a name for the given reflected method. The resulting name will be in a resolved state. */
158 public static MemberName make(Method m) {
159 return make(m, false);
160 }
161
162 @SuppressWarnings("LeakingThisInConstructor")
163 private MemberName(Method m, boolean wantSpecial) {
164 m.getClass(); // NPE check
165 // fill in vmtarget, vmindex while we have m in hand:
166 MethodHandleNatives.init(this, m);
167 if (clazz == null) { // MHN.init failed
168 if (m.getDeclaringClass() == MethodHandle.class &&
169 isMethodHandleInvokeName(m.getName())) {
170 // The JVM did not reify this signature-polymorphic instance.
171 // Need a special case here.
172 // See comments on MethodHandleNatives.linkMethod.
173 MethodType type = MethodType.methodType(m.getReturnType(), m.getParameterTypes());
174 int flags = flagsMods(IS_METHOD, m.getModifiers(), REF_invokeVirtual);
175 init(MethodHandle.class, m.getName(), type, flags);
176 if (isMethodHandleInvoke()) {
177 return;
178 }
179 }
180 throw new LinkageError(m.toString());
181 }
182 assert(isResolved() && this.clazz != null);
183 this.name = m.getName();
184 if (this.type == null) {
185 this.type = new Object[] { m.getReturnType(), m.getParameterTypes() };
186 }
187 if (wantSpecial) {
188 if (isAbstract()) {
189 throw new AbstractMethodError(this.toString());
190 }
191 if (getReferenceKind() == REF_invokeVirtual) {
192 changeReferenceKind(REF_invokeSpecial, REF_invokeVirtual);
193 } else if (getReferenceKind() == REF_invokeInterface) {
194 // invokeSpecial on a default method
195 changeReferenceKind(REF_invokeSpecial, REF_invokeInterface);
196 }
197 }
198 }
199
200 public static MemberName make(Method m, boolean wantSpecial) {
201 // Unreflected member names are resolved so intern them here.
202 MemberName tmp0 = null;
203 InternTransaction tx = new InternTransaction(m.getDeclaringClass());
204 while (tmp0 == null) {
205 MemberName tmp = new MemberName(m, wantSpecial);
206 tmp0 = tx.tryIntern(tmp);
207 }
208 return tmp0;
209 }
210
211 /**
212 * Create a name for the given reflected constructor. The resulting name
213 * will be in a resolved state.
214 */
215 @SuppressWarnings("LeakingThisInConstructor")
216 private MemberName(Constructor<?> ctor) {
217 ctor.getClass(); // NPE check
218 // fill in vmtarget, vmindex while we have ctor in hand:
219 MethodHandleNatives.init(this, ctor);
220 assert(isResolved() && this.clazz != null);
221 this.name = CONSTRUCTOR_NAME;
222 if (this.type == null) {
223 this.type = new Object[] { void.class, ctor.getParameterTypes() };
224 }
225 }
226
227 public static MemberName make(Constructor<?> ctor) {
228 // Unreflected member names are resolved so intern them here.
229 MemberName tmp0 = null;
230 InternTransaction tx = new InternTransaction(ctor.getDeclaringClass());
231 while (tmp0 == null) {
232 MemberName tmp = new MemberName(ctor);
233 tmp0 = tx.tryIntern(tmp);
234 }
235 return tmp0;
236 }
237
238 /** Create a name for the given reflected field. The resulting name will be in a resolved state.
239 */
240 public static MemberName make(Field field) {
241 return make(field, false);
242 }
243
244 @SuppressWarnings("LeakingThisInConstructor")
245 private MemberName(Field field, boolean makeSetter) {
246 field.getClass(); // NPE check
247 // fill in vmtarget, vmindex while we have field in hand:
248 MethodHandleNatives.init(this, field);
249 assert(isResolved() && this.clazz != null);
250 this.name = field.getName();
251 this.type = field.getType();
252 byte refKind = this.getReferenceKind();
253 assert(refKind == (isStatic() ? REF_getStatic : REF_getField));
254 if (makeSetter) {
255 assert((REF_putStatic - REF_getStatic) == (REF_putField - REF_getField));
256 changeReferenceKind((byte)(refKind + (REF_putStatic - REF_getStatic)), refKind);
257 }
258 }
259
260 public static MemberName make(Field field, boolean makeSetter) {
261 // Unreflected member names are resolved so intern them here.
262 MemberName tmp0 = null;
263 InternTransaction tx = new InternTransaction(field.getDeclaringClass());
264 while (tmp0 == null) {
265 MemberName tmp = new MemberName(field, makeSetter);
266 tmp0 = tx.tryIntern(tmp);
267 }
268 return tmp0;
269 }
270
271 /** Initialize a query. It is not resolved. */
272 private void init(Class<?> defClass, String name, Object type, int flags) {
273 // defining class is allowed to be null (for a naked name/type pair)
274 //name.toString(); // null check
275 //type.equals(type); // null check
276 // fill in fields:
277 this.clazz = defClass;
278 this.name = name;
279 this.type = type;
280 this.flags = flags;
281 assert(testAnyFlags(ALL_KINDS));
282 assert(this.resolution == null); // nobody should have touched this yet
283 //assert(referenceKindIsConsistent()); // do this after resolution
284 }
285
286 private void initResolved(boolean isResolved) {
287 assert(this.resolution == null); // not initialized yet!
288 if (!isResolved)
289 this.resolution = this;
290 assert(isResolved() == isResolved);
291 }
292
293 /**
294 * Helper method to intern this member name in the declaring class' member name table.
295 */
296 @SuppressWarnings("unchecked")
297 private MemberName intern(int transaction_token) {
298 return jla.internMemberName(clazz, this, transaction_token);
299 }
300
301 /**
302 * Helper method to obtain the transaction token for interning,
303 * given Class clazz.
304 * @param clazz
305 * @return
306 */
307 static private int internTxnToken(Class clazz) {
308 return clazz == null ? 0 : jla.getClassRedefinedCount(clazz);
309 }
310
311 /**
312 * Helper method to obtain the transaction token for interning, given this.
313 * @return
314 */
315 private int internTxnToken() {
316 return internTxnToken(clazz);
317 }
318
319 /**
320 * Helper method to conditionally intern cloned+modified member names.
321 */
322 private MemberName intern(MemberName likeThis, int transaction_token) {
323 if (likeThis.isResolved())
324 return intern(transaction_token);
325 else
326 return this;
327 }
328
329 /**
330 * Helper class to handle the case where the class checked for no
331 * redefinition may not be correct; resolution can end up with a different
332 * class.
333 */
334 static class InternTransaction {
335 Class<?> tx_class;
336 int txn_token;
337
338 InternTransaction(Class<?> tx_class) {
339 this.tx_class = tx_class;
340 this.txn_token = internTxnToken(tx_class);
341 }
342
343 /**
344 * If member_name is not resolved, returns member_name; if is resolved,
345 * attempts to intern member_name (once) while checking for races.
346 *
347 * @param member_name
348 * @return member_name if not resolved, null if racing, otherwise
349 * value of interned member_name.
350 */
351 MemberName tryIntern(MemberName member_name) {
352 if (member_name.isResolved()) {
353 if (member_name.getClass() != tx_class) {
354 Class prev_tx_class = tx_class;
355 int prev_txn_token = txn_token;
356 tx_class = member_name.getClass();
357 txn_token = internTxnToken(tx_class);
358 // Zero is a special case.
359 if (txn_token != 0 ||
360 prev_txn_token != internTxnToken(prev_tx_class)) {
361 // Resolved class is different and at least one
362 // redef of it occurred, therefore repeat with
363 // proper class for race consistency checking.
364 return null;
365 }
366 }
367 return member_name.intern(txn_token);
368 } else {
369 return member_name;
370 }
371 }
372 }
373
374 /** Return the declaring class of this member.
375 * In the case of a bare name and type, the declaring class will be null.
376 */
377 @Override
378 public Class<?> getDeclaringClass() {
379 return clazz;
380 }
381
382 /** Utility method producing the class loader of the declaring class. */
383 public ClassLoader getClassLoader() {
384 return clazz.getClassLoader();
385 }
386
387 /** Return the simple name of this member.
388 * For a type, it is the same as {@link Class#getSimpleName}.
389 * For a method or field, it is the simple name of the member.
390 * For a constructor, it is always {@code "<init>"}.
391 */
392 @Override
393 public String getName() {
394 if (name == null) {
395 expandFromVM();
396 if (name == null) {
397 return null;
398 }
399 }
400 return name;
401 }
402
403 public MethodType getMethodOrFieldType() {
404 if (isInvocable())
405 return getMethodType();
406 if (isGetter())
407 return MethodType.methodType(getFieldType());
408 if (isSetter())
409 return MethodType.methodType(void.class, getFieldType());
410 throw new InternalError("not a method or field: "+this);
411 }
412
518
519 /** Utility method to produce the signature of this member,
520 * used within the class file format to describe its type.
521 */
522 public String getSignature() {
523 if (type == null) {
524 expandFromVM();
525 if (type == null) {
526 return null;
527 }
528 }
529 if (isInvocable())
530 return BytecodeDescriptor.unparse(getMethodType());
531 else
532 return BytecodeDescriptor.unparse(getFieldType());
533 }
534
535 /** Return the modifier flags of this member.
536 * @see java.lang.reflect.Modifier
537 */
538 @Override
539 public int getModifiers() {
540 return (flags & RECOGNIZED_MODIFIERS);
541 }
542
543 /** Return the reference kind of this member, or zero if none.
544 */
545 public byte getReferenceKind() {
546 return (byte) ((flags >>> MN_REFERENCE_KIND_SHIFT) & MN_REFERENCE_KIND_MASK);
547 }
548 private boolean referenceKindIsConsistent() {
549 byte refKind = getReferenceKind();
550 if (refKind == REF_NONE) return isType();
551 if (isField()) {
552 assert(staticIsConsistent());
553 assert(MethodHandleNatives.refKindIsField(refKind));
554 } else if (isConstructor()) {
555 assert(refKind == REF_newInvokeSpecial || refKind == REF_invokeSpecial);
556 } else if (isMethod()) {
557 assert(staticIsConsistent());
558 assert(MethodHandleNatives.refKindIsMethod(refKind));
696 public boolean isNative() {
697 return Modifier.isNative(flags);
698 }
699 // let the rest (native, volatile, transient, etc.) be tested via Modifier.isFoo
700
701 // unofficial modifier flags, used by HotSpot:
702 static final int BRIDGE = 0x00000040;
703 static final int VARARGS = 0x00000080;
704 static final int SYNTHETIC = 0x00001000;
705 static final int ANNOTATION= 0x00002000;
706 static final int ENUM = 0x00004000;
707 /** Utility method to query the modifier flags of this member; returns false if the member is not a method. */
708 public boolean isBridge() {
709 return testAllFlags(IS_METHOD | BRIDGE);
710 }
711 /** Utility method to query the modifier flags of this member; returns false if the member is not a method. */
712 public boolean isVarargs() {
713 return testAllFlags(VARARGS) && isInvocable();
714 }
715 /** Utility method to query the modifier flags of this member; returns false if the member is not a method. */
716 @Override
717 public boolean isSynthetic() {
718 return testAllFlags(SYNTHETIC);
719 }
720
721 static final String CONSTRUCTOR_NAME = "<init>"; // the ever-popular
722
723 // modifiers exported by the JVM:
724 static final int RECOGNIZED_MODIFIERS = 0xFFFF;
725
726 // private flags, not part of RECOGNIZED_MODIFIERS:
727 static final int
728 IS_METHOD = MN_IS_METHOD, // method (not constructor)
729 IS_CONSTRUCTOR = MN_IS_CONSTRUCTOR, // constructor
730 IS_FIELD = MN_IS_FIELD, // field
731 IS_TYPE = MN_IS_TYPE, // nested type
732 CALLER_SENSITIVE = MN_CALLER_SENSITIVE; // @CallerSensitive annotation detected
733
734 static final int ALL_ACCESS = Modifier.PUBLIC | Modifier.PRIVATE | Modifier.PROTECTED;
735 static final int ALL_KINDS = IS_METHOD | IS_CONSTRUCTOR | IS_FIELD | IS_TYPE;
736 static final int IS_INVOCABLE = IS_METHOD | IS_CONSTRUCTOR;
759 }
760 /** Query whether this member is a type. */
761 public boolean isType() {
762 return testAllFlags(IS_TYPE);
763 }
764 /** Utility method to query whether this member is neither public, private, nor protected. */
765 public boolean isPackage() {
766 return !testAnyFlags(ALL_ACCESS);
767 }
768 /** Query whether this member has a CallerSensitive annotation. */
769 public boolean isCallerSensitive() {
770 return testAllFlags(CALLER_SENSITIVE);
771 }
772
773 /** Utility method to query whether this member is accessible from a given lookup class. */
774 public boolean isAccessibleFrom(Class<?> lookupClass) {
775 return VerifyAccess.isMemberAccessible(this.getDeclaringClass(), this.getDeclaringClass(), flags,
776 lookupClass, ALL_ACCESS|MethodHandles.Lookup.PACKAGE);
777 }
778
779 /**
780 * Calls down to the VM to fill in the fields. This method is
781 * synchronized to avoid racing calls.
782 */
783 private void expandFromVM() {
784 if (type != null) {
785 return;
786 }
787 if (!isResolved()) {
788 return;
789 }
790 MethodHandleNatives.expand(this);
791 }
792
793 // Capturing information from the Core Reflection API:
794 private static int flagsMods(int flags, int mods, byte refKind) {
795 assert((flags & RECOGNIZED_MODIFIERS) == 0);
796 assert((mods & ~RECOGNIZED_MODIFIERS) == 0);
797 assert((refKind & ~MN_REFERENCE_KIND_MASK) == 0);
798 return flags | mods | (refKind << MN_REFERENCE_KIND_SHIFT);
799 }
800
801
802
803 public MemberName asSpecial() {
804 switch (getReferenceKind()) {
805 case REF_invokeSpecial: return this;
806 case REF_invokeVirtual: return cloneAndChangeReferenceKindAndIntern(REF_invokeSpecial, REF_invokeVirtual);
807 case REF_invokeInterface: return cloneAndChangeReferenceKindAndIntern(REF_invokeSpecial, REF_invokeInterface);
808 case REF_newInvokeSpecial: return cloneAndChangeReferenceKindAndIntern(REF_invokeSpecial, REF_newInvokeSpecial);
809 }
810 throw new IllegalArgumentException(this.toString());
811 }
812 /** If this MN is not REF_newInvokeSpecial, return a clone with that ref. kind.
813 * In that case it must already be REF_invokeSpecial.
814 */
815 public MemberName asConstructor() {
816 switch (getReferenceKind()) {
817 case REF_invokeSpecial: return cloneAndChangeReferenceKindAndIntern(REF_newInvokeSpecial, REF_invokeSpecial);
818 case REF_newInvokeSpecial: return this;
819 }
820 throw new IllegalArgumentException(this.toString());
821 }
822 /** If this MN is a REF_invokeSpecial, return a clone with the "normal" kind
823 * REF_invokeVirtual; also switch either to REF_invokeInterface if clazz.isInterface.
824 * The end result is to get a fully virtualized version of the MN.
825 * (Note that resolving in the JVM will sometimes devirtualize, changing
826 * REF_invokeVirtual of a final to REF_invokeSpecial, and REF_invokeInterface
827 * in some corner cases to either of the previous two; this transform
828 * undoes that change under the assumption that it occurred.)
829 */
830 public MemberName asNormalOriginal() {
831 byte normalVirtual = clazz.isInterface() ? REF_invokeInterface : REF_invokeVirtual;
832 byte refKind = getReferenceKind();
833 byte newRefKind = refKind;
834 MemberName result = this;
835 switch (refKind) {
836 case REF_invokeInterface:
837 case REF_invokeVirtual:
838 case REF_invokeSpecial:
839 newRefKind = normalVirtual;
840 break;
841 }
842 if (newRefKind == refKind)
843 return this;
844 result = cloneAndChangeReferenceKindAndIntern(newRefKind, refKind);
845 assert(this.referenceKindIsConsistentWith(result.getReferenceKind()));
846 return result;
847 }
848
849 private MemberName cloneAndChangeReferenceKindAndIntern(byte refKind, byte oldKind) {
850 MemberName tmp0 = null;
851 while (tmp0 == null) {
852 int tx_token = internTxnToken();
853 tmp0 = clone().changeReferenceKind(refKind, oldKind).intern(this, tx_token);
854 }
855 return tmp0;
856 }
857
858 public boolean isGetter() {
859 return MethodHandleNatives.refKindIsGetter(getReferenceKind());
860 }
861 public boolean isSetter() {
862 return MethodHandleNatives.refKindIsSetter(getReferenceKind());
863 }
864 public MemberName asSetter() {
865 byte refKind = getReferenceKind();
866 assert(MethodHandleNatives.refKindIsGetter(refKind));
867 assert((REF_putStatic - REF_getStatic) == (REF_putField - REF_getField));
868 byte setterRefKind = (byte)(refKind + (REF_putField - REF_getField));
869 return cloneAndChangeReferenceKindAndIntern(setterRefKind, refKind);
870 }
871 /**
872 * Create a name for a signature-polymorphic invoker.
873 * This is a placeholder for a signature-polymorphic instance
874 * (of MH.invokeExact, etc.) that the JVM does not reify.
875 * See comments on {@link MethodHandleNatives#linkMethod}.
876 */
877 static MemberName makeMethodHandleInvoke(String name, MethodType type) {
878 return makeMethodHandleInvoke(name, type, MH_INVOKE_MODS | SYNTHETIC);
879 }
880 static MemberName makeMethodHandleInvoke(String name, MethodType type, int mods) {
881 MemberName mem = new MemberName(MethodHandle.class, name, type, REF_invokeVirtual);
882 mem.flags |= mods; // it's not resolved, but add these modifiers anyway
883 assert(mem.isMethodHandleInvoke()) : mem;
884 return mem;
885 }
886
887 // locally useful cloner
888 @Override protected MemberName clone() {
889 try {
890 return (MemberName) super.clone();
891 } catch (CloneNotSupportedException ex) {
892 throw newInternalError(ex);
893 }
894 }
895
896 /** Get the definition of this member name.
897 * This may be in a super-class of the declaring class of this member.
898 */
899 public MemberName getDefinition() {
900 if (!isResolved()) throw new IllegalStateException("must be resolved: "+this);
901 if (isType()) return this;
902 MemberName res = this.clone();
903 res.clazz = null;
904 res.type = null;
905 res.name = null;
906 res.resolution = res;
915 }
916 @Override
917 public boolean equals(Object that) {
918 return (that instanceof MemberName && this.equals((MemberName)that));
919 }
920
921 /** Decide if two member names have exactly the same symbolic content.
922 * Does not take into account any actual class members, so even if
923 * two member names resolve to the same actual member, they may
924 * be distinct references.
925 */
926 public boolean equals(MemberName that) {
927 if (this == that) return true;
928 if (that == null) return false;
929 return this.clazz == that.clazz
930 && this.getReferenceKind() == that.getReferenceKind()
931 && Objects.equals(this.name, that.name)
932 && Objects.equals(this.getType(), that.getType());
933 }
934
935 @Override
936 public int compareTo(Object o) {
937 MemberName that = (MemberName) o;
938
939 /* First test equals. This make the ordering checks easier because we
940 * don't have to be precise and can use hash codes.
941 */
942 if (equals(that)) {
943 return 0;
944 }
945
946 int diff = Integer.compare(this.name.hashCode(), that.name.hashCode());
947 if (diff != 0) {
948 return diff;
949 }
950
951 diff = this.getReferenceKind() - that.getReferenceKind();
952 if (diff != 0) {
953 return diff;
954 }
955
956 diff = Integer.compare(this.getType().hashCode(), that.getType().hashCode());
957 if (diff != 0) {
958 return diff;
959 }
960
961 // Hashcodes apparently collided, try more detail.
962 diff = this.name.compareTo(that.name);
963 if (diff != 0) {
964 return diff;
965 }
966
967 // The classes ought to all be equal anyway in the usual use of
968 // compareTo, so check these later,
969 // but before comparing getType.toString().
970 diff = Integer.compare(this.clazz.hashCode(),that.clazz.hashCode());
971 if (diff != 0) {
972 return diff;
973 }
974
975 diff = this.getType().toString().compareTo(that.getType().toString());
976 if (diff != 0) {
977 return diff;
978 }
979
980 diff = this.clazz.getName().compareTo(that.clazz.getName());
981 if (diff != 0) {
982 return diff;
983 }
984
985 ClassLoader thisCl = this.clazz.getClassLoader();
986 ClassLoader thatCl = that.clazz.getClassLoader();
987
988 if (thisCl == thatCl) return 0;
989
990 diff = Integer.compare(thisCl == null ? 0 : thisCl.hashCode(),
991 thatCl == null ? 0 : thatCl.hashCode());
992
993 return diff;
994 }
995
996 /** Query whether this member name is resolved to a non-static, non-final method.
997 */
998 public boolean hasReceiverTypeDispatch() {
999 return MethodHandleNatives.refKindDoesDispatch(getReferenceKind());
1000 }
1001
1002 /** Query whether this member name is resolved.
1003 * A resolved member name is one for which the JVM has found
1004 * a method, constructor, field, or type binding corresponding exactly to the name.
1005 * (Document?)
1006 */
1007 public boolean isResolved() {
1008 return resolution == null;
1009 }
1010
1011 void checkForTypeAlias() {
1012 if (isInvocable()) {
1013 MethodType type;
1014 if (this.type instanceof MethodType)
1015 type = (MethodType) this.type;
1016 else
1017 this.type = type = getMethodType();
1018 if (type.erase() == type) return;
1019 if (VerifyAccess.isTypeVisible(type, clazz)) return;
1020 throw new LinkageError("bad method type alias: "+type+" not visible from "+clazz);
1021 } else {
1022 Class<?> type;
1023 if (this.type instanceof Class<?>)
1024 type = (Class<?>) this.type;
1025 else
1026 this.type = type = getFieldType();
1027 if (VerifyAccess.isTypeVisible(type, clazz)) return;
1028 throw new LinkageError("bad field type alias: "+type+" not visible from "+clazz);
1029 }
1030 }
1097 else if (isMethod())
1098 ex = new NoSuchMethodException(message);
1099 else
1100 ex = new NoSuchFieldException(message);
1101 if (resolution instanceof Throwable)
1102 ex.initCause((Throwable) resolution);
1103 return ex;
1104 }
1105
1106 /** Actually making a query requires an access check. */
1107 /*non-public*/ static Factory getFactory() {
1108 return Factory.INSTANCE;
1109 }
1110 /** A factory type for resolving member names with the help of the VM.
1111 * TBD: Define access-safe public constructors for this factory.
1112 */
1113 /*non-public*/ static class Factory {
1114 private Factory() { } // singleton pattern
1115 static Factory INSTANCE = new Factory();
1116
1117 private final static int ALLOWED_FLAGS = ALL_KINDS;
1118
1119 /// Queries
1120 List<MemberName> getMembers(Class<?> defc,
1121 String matchName, Object matchType,
1122 int matchFlags, Class<?> lookupClass) {
1123 matchFlags &= ALLOWED_FLAGS;
1124 String matchSig = null;
1125 if (matchType != null) {
1126 matchSig = BytecodeDescriptor.unparse(matchType);
1127 if (matchSig.startsWith("("))
1128 matchFlags &= ~(ALL_KINDS & ~IS_INVOCABLE);
1129 else
1130 matchFlags &= ~(ALL_KINDS & ~IS_FIELD);
1131 }
1132 final int BUF_MAX = 0x2000;
1133 int len1 = matchName == null ? 10 : matchType == null ? 4 : 1;
1134 MemberName[] buf = newMemberBuffer(len1);
1135 int totalCount = 0;
1136 ArrayList<MemberName[]> bufs = null;
1137 int bufCount = 0;
1163 }
1164 result.addAll(Arrays.asList(buf).subList(0, bufCount));
1165 // Signature matching is not the same as type matching, since
1166 // one signature might correspond to several types.
1167 // So if matchType is a Class or MethodType, refilter the results.
1168 if (matchType != null && matchType != matchSig) {
1169 for (Iterator<MemberName> it = result.iterator(); it.hasNext();) {
1170 MemberName m = it.next();
1171 if (!matchType.equals(m.getType()))
1172 it.remove();
1173 }
1174 }
1175 return result;
1176 }
1177 /** Produce a resolved version of the given member.
1178 * Super types are searched (for inherited members) if {@code searchSupers} is true.
1179 * Access checking is performed on behalf of the given {@code lookupClass}.
1180 * If lookup fails or access is not permitted, null is returned.
1181 * Otherwise a fresh copy of the given member is returned, with modifier bits filled in.
1182 */
1183 private static MemberName resolve(byte refKind, MemberName ref, Class<?> lookupClass) {
1184 MemberName m = ref.clone(); // JVM will side-effect the ref
1185 assert(refKind == m.getReferenceKind());
1186 try {
1187 m = MethodHandleNatives.resolve(m, lookupClass);
1188 m.checkForTypeAlias();
1189 m.resolution = null;
1190 } catch (LinkageError ex) {
1191 // JVM reports that the "bytecode behavior" would get an error
1192 assert(!m.isResolved());
1193 m.resolution = ex;
1194 return m;
1195 }
1196 assert(m.referenceKindIsConsistent());
1197 m.initResolved(true);
1198 assert(m.vminfoIsConsistent());
1199 // m = m.intern(); // do not intern -- caller should intern instead.
1200 return m;
1201 }
1202 /** Produce a resolved version of the given member.
1203 * Super types are searched (for inherited members) if {@code searchSupers} is true.
1204 * Access checking is performed on behalf of the given {@code lookupClass}.
1205 * If lookup fails or access is not permitted, a {@linkplain ReflectiveOperationException} is thrown.
1206 * Otherwise a fresh copy of the given member is returned, with modifier bits filled in.
1207 */
1208 public
1209 <NoSuchMemberException extends ReflectiveOperationException>
1210 MemberName resolveOrFail(byte refKind, MemberName m, Class<?> lookupClass,
1211 Class<NoSuchMemberException> nsmClass)
1212 throws IllegalAccessException, NoSuchMemberException {
1213 MemberName result = resolveOrNot(refKind, m, lookupClass);
1214
1215 if (result.isResolved()) {
1216 return result;
1217 } else { // not resolved, throw exception
1218 ReflectiveOperationException ex = result.makeAccessException();
1219 if (ex instanceof IllegalAccessException) {
1220 throw (IllegalAccessException) ex;
1221 }
1222 throw nsmClass.cast(ex);
1223 }
1224 }
1225 /** Produce a resolved version of the given member.
1226 * Super types are searched (for inherited members) if {@code searchSupers} is true.
1227 * Access checking is performed on behalf of the given {@code lookupClass}.
1228 * If lookup fails or access is not permitted, return null.
1229 * Otherwise a fresh copy of the given member is returned, with modifier bits filled in.
1230 */
1231 public
1232 MemberName resolveOrNull(byte refKind, MemberName m, Class<?> lookupClass) {
1233 MemberName result = resolveOrNot(refKind, m, lookupClass);
1234 return result.isResolved() ? result : null;
1235 }
1236
1237 private static
1238 MemberName resolveOrNot(byte refKind, MemberName m, Class<?> lookupClass) {
1239 MemberName result = null;
1240 Class tx_class = m.getClass();
1241 while (result == null) { // iterate till no race.
1242 int txn_token = internTxnToken(tx_class);
1243
1244 MemberName result0 = resolve(refKind, m, lookupClass);
1245
1246 if (result0.isResolved()) {
1247 if (result0.getClass() != tx_class) {
1248 Class prev_tx_class = tx_class;
1249 int prev_txn_token = txn_token;
1250 tx_class = result0.getClass();
1251 txn_token = internTxnToken(tx_class);
1252 // Zero is a special case.
1253 if (txn_token != 0 ||
1254 prev_txn_token != internTxnToken(prev_tx_class)) {
1255 // Resolved class is different and at least one
1256 // redef of it occurred, therefore repeat with
1257 // proper class for race consistency checking.
1258 continue;
1259 }
1260 }
1261 result = result0.intern(txn_token);
1262 } else {
1263 return result0;
1264 }
1265 }
1266 return result;
1267 }
1268
1269 /** Return a list of all methods defined by the given class.
1270 * Super types are searched (for inherited members) if {@code searchSupers} is true.
1271 * Access checking is performed on behalf of the given {@code lookupClass}.
1272 * Inaccessible members are not added to the last.
1273 */
1274 public List<MemberName> getMethods(Class<?> defc, boolean searchSupers,
1275 Class<?> lookupClass) {
1276 return getMethods(defc, searchSupers, null, null, lookupClass);
1277 }
1278 /** Return a list of matching methods defined by the given class.
1279 * Super types are searched (for inherited members) if {@code searchSupers} is true.
1280 * Returned methods will match the name (if not null) and the type (if not null).
1281 * Access checking is performed on behalf of the given {@code lookupClass}.
1282 * Inaccessible members are not added to the last.
1283 */
1284 public List<MemberName> getMethods(Class<?> defc, boolean searchSupers,
1285 String name, MethodType type, Class<?> lookupClass) {
1286 int matchFlags = IS_METHOD | (searchSupers ? SEARCH_ALL_SUPERS : 0);
1287 return getMembers(defc, name, type, matchFlags, lookupClass);
1288 }
1314 return getMembers(defc, name, type, matchFlags, lookupClass);
1315 }
1316 /** Return a list of all nested types defined by the given class.
1317 * Super types are searched (for inherited members) if {@code searchSupers} is true.
1318 * Access checking is performed on behalf of the given {@code lookupClass}.
1319 * Inaccessible members are not added to the last.
1320 */
1321 public List<MemberName> getNestedTypes(Class<?> defc, boolean searchSupers,
1322 Class<?> lookupClass) {
1323 int matchFlags = IS_TYPE | (searchSupers ? SEARCH_ALL_SUPERS : 0);
1324 return getMembers(defc, null, null, matchFlags, lookupClass);
1325 }
1326 private static MemberName[] newMemberBuffer(int length) {
1327 MemberName[] buf = new MemberName[length];
1328 // fill the buffer with dummy structs for the JVM to fill in
1329 for (int i = 0; i < length; i++)
1330 buf[i] = new MemberName();
1331 return buf;
1332 }
1333 }
1334 }
|