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();
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
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 }
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,
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 java.util.Objects;
46
47 /**
48 * A {@code MemberName} is a compact symbolic datum which fully characterizes
49 * a method or field reference.
50 * A member name refers to a field, method, constructor, or member type.
51 * Every member name has a simple name (a string) and a type (either a Class or MethodType).
52 * A member name may also have a non-null declaring class, or it may be simply
53 * a naked name/type pair.
54 * A member name may also have non-zero modifier flags.
55 * Finally, a member name may be either resolved or unresolved.
56 * If it is resolved, the existence of the named
57 * <p>
58 * Whether resolved or not, a member name provides no access rights or
59 * invocation capability to its possessor. It is merely a compact
60 * representation of all symbolic information necessary to link to
61 * and properly use the named member.
62 * <p>
63 * When resolved, a member name's internal implementation may include references to JVM metadata.
64 * This representation is stateless and only descriptive.
65 * It provides no private information and no capability to use the member.
66 * <p>
67 * By contrast, a {@linkplain java.lang.reflect.Method} contains fuller information
68 * about the internals of a method (except its bytecodes) and also
69 * allows invocation. A MemberName is much lighter than a Method,
70 * since it contains about 7 fields to the 16 of Method (plus its sub-arrays),
71 * and those seven fields omit much of the information in Method.
72 * @author jrose
73 */
74 @SuppressWarnings("rawtypes") //Comparable in next line
75 /*non-public*/ final class MemberName implements Member, Comparable, Cloneable {
76 private Class<?> clazz; // class in which the method is defined
77 private String name; // may be null if not yet materialized
78 private Object type; // may be null if not yet materialized
79 private int flags; // modifier bits; see reflect.Modifier
80 //@Injected JVM_Method* vmtarget;
81 //@Injected int vmindex;
82 private Object resolution; // if null, this guy is resolved
83
84 // bare-bones constructor; the JVM will fill it in
85 MemberName() { }
86
87 /** Create a name for the given class. The resulting name will be in a resolved state. */
88 public MemberName(Class<?> type) {
89 init(type.getDeclaringClass(), type.getSimpleName(), type,
90 flagsMods(IS_TYPE, type.getModifiers(), REF_NONE));
91 initResolved(true);
92 }
93
94 // Construction from symbolic parts, for queries:
95 /** Create a field or type name from the given components:
96 * Declaring class, name, type, reference kind.
97 * The declaring class may be supplied as null if this is to be a bare name and type.
98 * The resulting name will in an unresolved state.
99 */
100 public MemberName(Class<?> defClass, String name, Class<?> type, byte refKind) {
101 init(defClass, name, type, flagsMods(IS_FIELD, 0, refKind));
102 initResolved(false);
103 }
104
105 /** Create a field or type name from the given components: Declaring class, name, type.
106 * The declaring class may be supplied as null if this is to be a bare name and type.
107 * The modifier flags default to zero.
108 * The resulting name will in an unresolved state.
109 */
110 public MemberName(Class<?> defClass, String name, Class<?> type, Void unused) {
111 this(defClass, name, type, REF_NONE);
112 initResolved(false);
113 }
114
115 /** Create a method or constructor name from the given components: Declaring class, name, type, modifiers.
116 * It will be a constructor if and only if the name is {@code "<init>"}.
117 * The declaring class may be supplied as null if this is to be a bare name and type.
118 * The last argument is optional, a boolean which requests REF_invokeSpecial.
119 * The resulting name will in an unresolved state.
120 */
121 public MemberName(Class<?> defClass, String name, MethodType type, byte refKind) {
122 int initFlags = (name != null && name.equals(CONSTRUCTOR_NAME) ? IS_CONSTRUCTOR : IS_METHOD);
123 init(defClass, name, type, flagsMods(initFlags, 0, refKind));
124 initResolved(false);
125 }
126
127 /** Create a method, constructor, or field name from the given components:
128 * Reference kind, declaring class, name, type.
129 */
130 public MemberName(byte refKind, Class<?> defClass, String name, Object type) {
131 int kindFlags;
132 if (MethodHandleNatives.refKindIsField(refKind)) {
133 kindFlags = IS_FIELD;
134 if (!(type instanceof Class))
135 throw newIllegalArgumentException("not a field type");
136 } else if (MethodHandleNatives.refKindIsMethod(refKind)) {
137 kindFlags = IS_METHOD;
138 if (!(type instanceof MethodType))
139 throw newIllegalArgumentException("not a method type");
140 } else if (refKind == REF_newInvokeSpecial) {
141 kindFlags = IS_CONSTRUCTOR;
142 if (!(type instanceof MethodType) ||
143 !CONSTRUCTOR_NAME.equals(name))
144 throw newIllegalArgumentException("not a constructor type or name");
145 } else {
146 throw newIllegalArgumentException("bad reference kind "+refKind);
147 }
148 init(defClass, name, type, flagsMods(kindFlags, 0, refKind));
149 initResolved(false);
150 }
151
152 /** Create a name for the given reflected method. The resulting name will be in a resolved state. */
153 public static MemberName make(Method m) {
154 return make(m, false);
155 }
156
157 @SuppressWarnings("LeakingThisInConstructor")
158 private MemberName(Method m, boolean wantSpecial) {
159 m.getClass(); // NPE check
160 // fill in vmtarget, vmindex while we have m in hand:
161 MethodHandleNatives.init(this, m);
162 if (clazz == null) { // MHN.init failed
163 if (m.getDeclaringClass() == MethodHandle.class &&
164 isMethodHandleInvokeName(m.getName())) {
165 // The JVM did not reify this signature-polymorphic instance.
166 // Need a special case here.
167 // See comments on MethodHandleNatives.linkMethod.
168 MethodType type = MethodType.methodType(m.getReturnType(), m.getParameterTypes());
169 int flags = flagsMods(IS_METHOD, m.getModifiers(), REF_invokeVirtual);
170 init(MethodHandle.class, m.getName(), type, flags);
171 if (isMethodHandleInvoke()) {
172 return;
173 }
174 }
175 throw new LinkageError(m.toString());
176 }
177 assert(isResolved() && this.clazz != null);
178 this.name = m.getName();
179 if (this.type == null) {
180 this.type = new Object[] { m.getReturnType(), m.getParameterTypes() };
181 }
182 if (wantSpecial) {
183 if (isAbstract()) {
184 throw new AbstractMethodError(this.toString());
185 }
186 if (getReferenceKind() == REF_invokeVirtual) {
187 changeReferenceKind(REF_invokeSpecial, REF_invokeVirtual);
188 } else if (getReferenceKind() == REF_invokeInterface) {
189 // invokeSpecial on a default method
190 changeReferenceKind(REF_invokeSpecial, REF_invokeInterface);
191 }
192 }
193 }
194
195 public static MemberName make(Method m, boolean wantSpecial) {
196 MemberName tmp = new MemberName(m, wantSpecial);
197 // Unreflected member names are resolved so intern them here.
198 return tmp.intern();
199 }
200
201 /**
202 * Create a name for the given reflected constructor. The resulting name
203 * will be in a resolved state.
204 */
205 @SuppressWarnings("LeakingThisInConstructor")
206 private MemberName(Constructor<?> ctor) {
207 ctor.getClass(); // NPE check
208 // fill in vmtarget, vmindex while we have ctor in hand:
209 MethodHandleNatives.init(this, ctor);
210 assert(isResolved() && this.clazz != null);
211 this.name = CONSTRUCTOR_NAME;
212 if (this.type == null) {
213 this.type = new Object[] { void.class, ctor.getParameterTypes() };
214 }
215 }
216
217 static public MemberName make(Constructor<?> ctor) {
218 MemberName tmp = new MemberName(ctor);
219 // Unreflected member names are resolved so intern them here.
220 return tmp.intern();
221 }
222
223
224 /** Create a name for the given reflected field. The resulting name will be in a resolved state.
225 */
226 public static MemberName make(Field field) {
227 return make(field, false);
228 }
229
230 @SuppressWarnings("LeakingThisInConstructor")
231 private MemberName(Field field, boolean makeSetter) {
232 field.getClass(); // NPE check
233 // fill in vmtarget, vmindex while we have field in hand:
234 MethodHandleNatives.init(this, field);
235 assert(isResolved() && this.clazz != null);
236 this.name = field.getName();
237 this.type = field.getType();
238 byte refKind = this.getReferenceKind();
239 assert(refKind == (isStatic() ? REF_getStatic : REF_getField));
240 if (makeSetter) {
241 assert((REF_putStatic - REF_getStatic) == (REF_putField - REF_getField));
242 changeReferenceKind((byte)(refKind + (REF_putStatic - REF_getStatic)), refKind);
243 }
244 }
245
246 static public MemberName make(Field field, boolean makeSetter) {
247 MemberName tmp = new MemberName(field, makeSetter);
248 // Unreflected member names are resolved so intern them here.
249 return tmp.intern();
250 }
251
252 /** Initialize a query. It is not resolved. */
253 private void init(Class<?> defClass, String name, Object type, int flags) {
254 // defining class is allowed to be null (for a naked name/type pair)
255 //name.toString(); // null check
256 //type.equals(type); // null check
257 // fill in fields:
258 this.clazz = defClass;
259 this.name = name;
260 this.type = type;
261 this.flags = flags;
262 assert(testAnyFlags(ALL_KINDS));
263 assert(this.resolution == null); // nobody should have touched this yet
264 //assert(referenceKindIsConsistent()); // do this after resolution
265 }
266
267 private void initResolved(boolean isResolved) {
268 assert(this.resolution == null); // not initialized yet!
269 if (!isResolved)
270 this.resolution = this;
271 assert(isResolved() == isResolved);
272 }
273
274 /**
275 * Helper method to intern this member name in the declaring class' member name table.
276 */
277 @SuppressWarnings("unchecked")
278 private MemberName intern() {
279 return clazz.internMemberName(this);
280 }
281
282 /** Return the declaring class of this member.
283 * In the case of a bare name and type, the declaring class will be null.
284 */
285 public Class<?> getDeclaringClass() {
286 return clazz;
287 }
288
289 /** Utility method producing the class loader of the declaring class. */
290 public ClassLoader getClassLoader() {
291 return clazz.getClassLoader();
292 }
293
294 /** Return the simple name of this member.
295 * For a type, it is the same as {@link Class#getSimpleName}.
296 * For a method or field, it is the simple name of the member.
297 * For a constructor, it is always {@code "<init>"}.
298 */
299 public String getName() {
300 if (name == null) {
301 expandFromVM();
663 }
664 /** Query whether this member is a type. */
665 public boolean isType() {
666 return testAllFlags(IS_TYPE);
667 }
668 /** Utility method to query whether this member is neither public, private, nor protected. */
669 public boolean isPackage() {
670 return !testAnyFlags(ALL_ACCESS);
671 }
672 /** Query whether this member has a CallerSensitive annotation. */
673 public boolean isCallerSensitive() {
674 return testAllFlags(CALLER_SENSITIVE);
675 }
676
677 /** Utility method to query whether this member is accessible from a given lookup class. */
678 public boolean isAccessibleFrom(Class<?> lookupClass) {
679 return VerifyAccess.isMemberAccessible(this.getDeclaringClass(), this.getDeclaringClass(), flags,
680 lookupClass, ALL_ACCESS|MethodHandles.Lookup.PACKAGE);
681 }
682
683 /**
684 * Calls down to the VM to fill in the fields. This method is
685 * synchronized to avoid racing calls.
686 */
687 private void expandFromVM() {
688 if (type != null) {
689 return;
690 }
691 if (!isResolved()) {
692 return;
693 }
694 MethodHandleNatives.expand(this);
695 }
696
697 // Capturing information from the Core Reflection API:
698 private static int flagsMods(int flags, int mods, byte refKind) {
699 assert((flags & RECOGNIZED_MODIFIERS) == 0);
700 assert((mods & ~RECOGNIZED_MODIFIERS) == 0);
701 assert((refKind & ~MN_REFERENCE_KIND_MASK) == 0);
702 return flags | mods | (refKind << MN_REFERENCE_KIND_SHIFT);
703 }
704 public MemberName asSpecial() {
705 switch (getReferenceKind()) {
706 case REF_invokeSpecial: return this;
707 case REF_invokeVirtual: return clone().changeReferenceKind(REF_invokeSpecial, REF_invokeVirtual);
708 case REF_invokeInterface: return clone().changeReferenceKind(REF_invokeSpecial, REF_invokeInterface);
709 case REF_newInvokeSpecial: return clone().changeReferenceKind(REF_invokeSpecial, REF_newInvokeSpecial);
710 }
711 throw new IllegalArgumentException(this.toString());
712 }
713 /** If this MN is not REF_newInvokeSpecial, return a clone with that ref. kind.
714 * In that case it must already be REF_invokeSpecial.
715 */
716 public MemberName asConstructor() {
717 switch (getReferenceKind()) {
718 case REF_invokeSpecial: return clone().changeReferenceKind(REF_newInvokeSpecial, REF_invokeSpecial);
719 case REF_newInvokeSpecial: return this;
720 }
721 throw new IllegalArgumentException(this.toString());
722 }
723 /** If this MN is a REF_invokeSpecial, return a clone with the "normal" kind
729 * undoes that change under the assumption that it occurred.)
730 */
731 public MemberName asNormalOriginal() {
732 byte normalVirtual = clazz.isInterface() ? REF_invokeInterface : REF_invokeVirtual;
733 byte refKind = getReferenceKind();
734 byte newRefKind = refKind;
735 MemberName result = this;
736 switch (refKind) {
737 case REF_invokeInterface:
738 case REF_invokeVirtual:
739 case REF_invokeSpecial:
740 newRefKind = normalVirtual;
741 break;
742 }
743 if (newRefKind == refKind)
744 return this;
745 result = clone().changeReferenceKind(newRefKind, refKind);
746 assert(this.referenceKindIsConsistentWith(result.getReferenceKind()));
747 return result;
748 }
749 public boolean isGetter() {
750 return MethodHandleNatives.refKindIsGetter(getReferenceKind());
751 }
752 public boolean isSetter() {
753 return MethodHandleNatives.refKindIsSetter(getReferenceKind());
754 }
755 public MemberName asSetter() {
756 byte refKind = getReferenceKind();
757 assert(MethodHandleNatives.refKindIsGetter(refKind));
758 assert((REF_putStatic - REF_getStatic) == (REF_putField - REF_getField));
759 byte setterRefKind = (byte)(refKind + (REF_putField - REF_getField));
760 return clone().changeReferenceKind(setterRefKind, refKind);
761 }
762 /**
763 * Create a name for a signature-polymorphic invoker.
764 * This is a placeholder for a signature-polymorphic instance
765 * (of MH.invokeExact, etc.) that the JVM does not reify.
766 * See comments on {@link MethodHandleNatives#linkMethod}.
767 */
768 static MemberName makeMethodHandleInvoke(String name, MethodType type) {
769 return makeMethodHandleInvoke(name, type, MH_INVOKE_MODS | SYNTHETIC);
770 }
771 static MemberName makeMethodHandleInvoke(String name, MethodType type, int mods) {
772 MemberName mem = new MemberName(MethodHandle.class, name, type, REF_invokeVirtual);
773 mem.flags |= mods; // it's not resolved, but add these modifiers anyway
774 assert(mem.isMethodHandleInvoke()) : mem;
775 return mem;
776 }
777
778 // locally useful cloner
779 @Override protected MemberName clone() {
780 try {
781 return (MemberName) super.clone();
782 } catch (CloneNotSupportedException ex) {
783 throw newInternalError(ex);
784 }
785 }
786
787 /** Get the definition of this member name.
788 * This may be in a super-class of the declaring class of this member.
789 */
790 public MemberName getDefinition() {
791 if (!isResolved()) throw new IllegalStateException("must be resolved: "+this);
792 if (isType()) return this;
793 MemberName res = this.clone();
794 res.clazz = null;
795 res.type = null;
796 res.name = null;
797 res.resolution = res;
806 }
807 @Override
808 public boolean equals(Object that) {
809 return (that instanceof MemberName && this.equals((MemberName)that));
810 }
811
812 /** Decide if two member names have exactly the same symbolic content.
813 * Does not take into account any actual class members, so even if
814 * two member names resolve to the same actual member, they may
815 * be distinct references.
816 */
817 public boolean equals(MemberName that) {
818 if (this == that) return true;
819 if (that == null) return false;
820 return this.clazz == that.clazz
821 && this.getReferenceKind() == that.getReferenceKind()
822 && Objects.equals(this.name, that.name)
823 && Objects.equals(this.getType(), that.getType());
824 }
825
826 @Override
827 public int compareTo(Object o) {
828 MemberName that = (MemberName) o;
829
830 /* First try an equals. This make the ordering checks easier because we
831 * don't have to be precise and can use hash codes.
832 */
833 if (equals(that)) {
834 return 0;
835 }
836
837 final int clazzDiff = this.clazz.hashCode() - that.clazz.hashCode();
838 if (clazzDiff != 0) {
839 return clazzDiff;
840 }
841
842 final int kindDiff = this.getReferenceKind() - that.getReferenceKind();
843 if (kindDiff != 0) {
844 return kindDiff;
845 }
846
847 final int nameDiff = this.name.hashCode() - that.name.hashCode();
848 if (nameDiff != 0) {
849 return nameDiff;
850 }
851
852 final int typeDiff = this.getType().hashCode() - that.getType().hashCode();
853 if (typeDiff != 0) {
854 return typeDiff;
855 }
856
857 // In the unlikely case all values above are equal we just return 1.
858 return 1;
859 }
860 /** Query whether this member name is resolved to a non-static, non-final method.
861 */
862 public boolean hasReceiverTypeDispatch() {
863 return MethodHandleNatives.refKindDoesDispatch(getReferenceKind());
864 }
865
866 /** Query whether this member name is resolved.
867 * A resolved member name is one for which the JVM has found
868 * a method, constructor, field, or type binding corresponding exactly to the name.
869 * (Document?)
870 */
871 public boolean isResolved() {
872 return resolution == null;
873 }
874
875 void checkForTypeAlias() {
876 if (isInvocable()) {
877 MethodType type;
878 if (this.type instanceof MethodType)
879 type = (MethodType) this.type;
880 else
881 this.type = type = getMethodType();
882 if (type.erase() == type) return;
883 if (VerifyAccess.isTypeVisible(type, clazz)) return;
884 throw new LinkageError("bad method type alias: "+type+" not visible from "+clazz);
885 } else {
886 Class<?> type;
887 if (this.type instanceof Class<?>)
888 type = (Class<?>) this.type;
889 else
890 this.type = type = getFieldType();
891 if (VerifyAccess.isTypeVisible(type, clazz)) return;
892 throw new LinkageError("bad field type alias: "+type+" not visible from "+clazz);
893 }
894 }
1034 MemberName m = it.next();
1035 if (!matchType.equals(m.getType()))
1036 it.remove();
1037 }
1038 }
1039 return result;
1040 }
1041 /** Produce a resolved version of the given member.
1042 * Super types are searched (for inherited members) if {@code searchSupers} is true.
1043 * Access checking is performed on behalf of the given {@code lookupClass}.
1044 * If lookup fails or access is not permitted, null is returned.
1045 * Otherwise a fresh copy of the given member is returned, with modifier bits filled in.
1046 */
1047 private MemberName resolve(byte refKind, MemberName ref, Class<?> lookupClass) {
1048 MemberName m = ref.clone(); // JVM will side-effect the ref
1049 assert(refKind == m.getReferenceKind());
1050 try {
1051 m = MethodHandleNatives.resolve(m, lookupClass);
1052 m.checkForTypeAlias();
1053 m.resolution = null;
1054 m.intern();
1055 } catch (LinkageError ex) {
1056 // JVM reports that the "bytecode behavior" would get an error
1057 assert(!m.isResolved());
1058 m.resolution = ex;
1059 return m;
1060 }
1061 assert(m.referenceKindIsConsistent());
1062 m.initResolved(true);
1063 assert(m.vminfoIsConsistent());
1064 return m;
1065 }
1066 /** Produce a resolved version of the given member.
1067 * Super types are searched (for inherited members) if {@code searchSupers} is true.
1068 * Access checking is performed on behalf of the given {@code lookupClass}.
1069 * If lookup fails or access is not permitted, a {@linkplain ReflectiveOperationException} is thrown.
1070 * Otherwise a fresh copy of the given member is returned, with modifier bits filled in.
1071 */
1072 public
1073 <NoSuchMemberException extends ReflectiveOperationException>
1074 MemberName resolveOrFail(byte refKind, MemberName m, Class<?> lookupClass,
1142 return getMembers(defc, name, type, matchFlags, lookupClass);
1143 }
1144 /** Return a list of all nested types defined by the given class.
1145 * Super types are searched (for inherited members) if {@code searchSupers} is true.
1146 * Access checking is performed on behalf of the given {@code lookupClass}.
1147 * Inaccessible members are not added to the last.
1148 */
1149 public List<MemberName> getNestedTypes(Class<?> defc, boolean searchSupers,
1150 Class<?> lookupClass) {
1151 int matchFlags = IS_TYPE | (searchSupers ? SEARCH_ALL_SUPERS : 0);
1152 return getMembers(defc, null, null, matchFlags, lookupClass);
1153 }
1154 private static MemberName[] newMemberBuffer(int length) {
1155 MemberName[] buf = new MemberName[length];
1156 // fill the buffer with dummy structs for the JVM to fill in
1157 for (int i = 0; i < length; i++)
1158 buf[i] = new MemberName();
1159 return buf;
1160 }
1161 }
1162 }
|