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 }
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 import java.util.Objects;
42 import sun.misc.JavaLangAccess;
43 import sun.misc.SharedSecrets;
44
45 import static java.lang.invoke.MethodHandleNatives.Constants.*;
46 import static java.lang.invoke.MethodHandleStatics.*;
47 import sun.misc.Unsafe;
48
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 * <p>
60 * Whether resolved or not, a member name provides no access rights or
61 * invocation capability to its possessor. It is merely a compact
62 * representation of all symbolic information necessary to link to
63 * and properly use the named member.
64 * <p>
65 * When resolved, a member name's internal implementation may include references to JVM metadata.
66 * This representation is stateless and only descriptive.
67 * It provides no private information and no capability to use the member.
68 * Resolved MemberNames are always interned (except for Class MemberNames)
69 * which allows updating when classes are redefined.
70 * <p>
71 * By contrast, a {@linkplain java.lang.reflect.Method} contains fuller information
72 * about the internals of a method (except its bytecodes) and also
73 * allows invocation. A MemberName is much lighter than a Method,
74 * since it contains about 7 fields to the 16 of Method (plus its sub-arrays),
75 * and those seven fields omit much of the information in Method.
76 * @author jrose
77 */
78 @SuppressWarnings("rawtypes") //Comparable in next line
79 /*non-public*/ final class MemberName implements Member, Comparable, Cloneable {
80 private Class<?> clazz; // class in which the method is defined
81 private String name; // may be null if not yet materialized
82 private Object type; // may be null if not yet materialized
83 private int flags; // modifier bits; see reflect.Modifier
84 private volatile MemberName next; // used for a linked list of MemberNames known to VM
85 //@Injected JVM_Method* vmtarget;
86 //@Injected int vmindex;
87 private Object resolution; // if null, this guy is resolved
88
89 private static final JavaLangAccess jla = SharedSecrets.getJavaLangAccess();
90 private static final Unsafe unsafe = Unsafe.getUnsafe();
91 static void storeFence() {
92 unsafe.storeFence();
93 }
94
95 // bare-bones constructor; the JVM will fill it in
96 MemberName() { }
97
98 /** Create a name for the given class. The resulting name will be in a resolved state. */
99 public MemberName(Class<?> type) {
100 init(type.getDeclaringClass(), type.getSimpleName(), type,
101 flagsMods(IS_TYPE, type.getModifiers(), REF_NONE));
102 initResolved(true);
103 }
104
105 // Construction from symbolic parts, for queries:
106 /** Create a field or type name from the given components:
107 * Declaring class, name, type, reference kind.
108 * The declaring class may be supplied as null if this is to be a bare name and type.
109 * The resulting name will in an unresolved state.
110 */
111 public MemberName(Class<?> defClass, String name, Class<?> type, byte refKind) {
112 init(defClass, name, type, flagsMods(IS_FIELD, 0, refKind));
113 initResolved(false);
114 }
115
116 /** Create a field or type name from the given components: Declaring class, name, type.
117 * The declaring class may be supplied as null if this is to be a bare name and type.
118 * The modifier flags default to zero.
119 * The resulting name will in an unresolved state.
120 */
121 public MemberName(Class<?> defClass, String name, Class<?> type, Void unused) {
122 this(defClass, name, type, REF_NONE);
123 initResolved(false);
124 }
125
126 /** Create a method or constructor name from the given components: Declaring class, name, type, modifiers.
127 * It will be a constructor if and only if the name is {@code "<init>"}.
128 * The declaring class may be supplied as null if this is to be a bare name and type.
129 * The last argument is optional, a boolean which requests REF_invokeSpecial.
130 * The resulting name will in an unresolved state.
131 */
132 public MemberName(Class<?> defClass, String name, MethodType type, byte refKind) {
133 int initFlags = (name != null && name.equals(CONSTRUCTOR_NAME) ? IS_CONSTRUCTOR : IS_METHOD);
134 init(defClass, name, type, flagsMods(initFlags, 0, refKind));
135 initResolved(false);
136 }
137
138 /** Create a method, constructor, or field name from the given components:
139 * Reference kind, declaring class, name, type.
140 */
141 public MemberName(byte refKind, Class<?> defClass, String name, Object type) {
142 int kindFlags;
143 if (MethodHandleNatives.refKindIsField(refKind)) {
144 kindFlags = IS_FIELD;
145 if (!(type instanceof Class))
146 throw newIllegalArgumentException("not a field type");
147 } else if (MethodHandleNatives.refKindIsMethod(refKind)) {
148 kindFlags = IS_METHOD;
149 if (!(type instanceof MethodType))
150 throw newIllegalArgumentException("not a method type");
151 } else if (refKind == REF_newInvokeSpecial) {
152 kindFlags = IS_CONSTRUCTOR;
153 if (!(type instanceof MethodType) ||
154 !CONSTRUCTOR_NAME.equals(name))
155 throw newIllegalArgumentException("not a constructor type or name");
156 } else {
157 throw newIllegalArgumentException("bad reference kind "+refKind);
158 }
159 init(defClass, name, type, flagsMods(kindFlags, 0, refKind));
160 initResolved(false);
161 }
162
163 /** Create a name for the given reflected method. The resulting name will be in a resolved state. */
164 public static MemberName make(Method m) {
165 return make(m, false);
166 }
167
168 @SuppressWarnings("LeakingThisInConstructor")
169 private MemberName(Method m, boolean wantSpecial) {
170 m.getClass(); // NPE check
171 // fill in vmtarget, vmindex while we have m in hand:
172 MethodHandleNatives.init(this, m);
173 if (clazz == null) { // MHN.init failed
174 if (m.getDeclaringClass() == MethodHandle.class &&
175 isMethodHandleInvokeName(m.getName())) {
176 // The JVM did not reify this signature-polymorphic instance.
177 // Need a special case here.
178 // See comments on MethodHandleNatives.linkMethod.
179 MethodType type = MethodType.methodType(m.getReturnType(), m.getParameterTypes());
180 int flags = flagsMods(IS_METHOD, m.getModifiers(), REF_invokeVirtual);
181 init(MethodHandle.class, m.getName(), type, flags);
182 if (isMethodHandleInvoke()) {
183 return;
184 }
185 }
186 throw new LinkageError(m.toString());
187 }
188 assert(isResolved() && this.clazz != null);
189 this.name = m.getName();
190 if (this.type == null) {
191 this.type = new Object[] { m.getReturnType(), m.getParameterTypes() };
192 }
193 if (wantSpecial) {
194 if (isAbstract()) {
195 throw new AbstractMethodError(this.toString());
196 }
197 if (getReferenceKind() == REF_invokeVirtual) {
198 changeReferenceKind(REF_invokeSpecial, REF_invokeVirtual);
199 } else if (getReferenceKind() == REF_invokeInterface) {
200 // invokeSpecial on a default method
201 changeReferenceKind(REF_invokeSpecial, REF_invokeInterface);
202 }
203 }
204 }
205
206 public static MemberName make(Method m, boolean wantSpecial) {
207 // Unreflected member names are resolved so intern them here.
208 MemberName tmp0 = null;
209 InternTransaction tx = new InternTransaction(m.getDeclaringClass());
210 while (tmp0 == null) {
211 MemberName tmp = new MemberName(m, wantSpecial);
212 tmp0 = tx.tryIntern(tmp);
213 }
214 return tmp0;
215 }
216
217 @SuppressWarnings("LeakingThisInConstructor")
218 private MemberName(Constructor<?> ctor) {
219 ctor.getClass(); // NPE check
220 // fill in vmtarget, vmindex while we have ctor in hand:
221 MethodHandleNatives.init(this, ctor);
222 assert(isResolved() && this.clazz != null);
223 this.name = CONSTRUCTOR_NAME;
224 if (this.type == null) {
225 this.type = new Object[] { void.class, ctor.getParameterTypes() };
226 }
227 }
228
229 /**
230 * Create a name for the given reflected constructor.
231 * The resulting name will be in a resolved state.
232 */
233 public static MemberName make(Constructor<?> ctor) {
234 // Unreflected member names are resolved so intern them here.
235 MemberName tmp0 = null;
236 InternTransaction tx = new InternTransaction(ctor.getDeclaringClass());
237 while (tmp0 == null) {
238 MemberName tmp = new MemberName(ctor);
239 tmp0 = tx.tryIntern(tmp);
240 }
241 return tmp0;
242 }
243
244 /**
245 * Create a name for the given reflected field.
246 * The resulting name will be in a resolved state.
247 */
248 public static MemberName make(Field field) {
249 return make(field, false);
250 }
251
252 @SuppressWarnings("LeakingThisInConstructor")
253 private MemberName(Field field, boolean makeSetter) {
254 field.getClass(); // NPE check
255 // fill in vmtarget, vmindex while we have field in hand:
256 MethodHandleNatives.init(this, field);
257 assert(isResolved() && this.clazz != null);
258 this.name = field.getName();
259 this.type = field.getType();
260 byte refKind = this.getReferenceKind();
261 assert(refKind == (isStatic() ? REF_getStatic : REF_getField));
262 if (makeSetter) {
263 assert((REF_putStatic - REF_getStatic) == (REF_putField - REF_getField));
264 changeReferenceKind((byte)(refKind + (REF_putStatic - REF_getStatic)), refKind);
265 }
266 }
267
268 /**
269 * Create a name for the given reflected field, optionally making it a setter.
270 * The resulting name will be in a resolved state.
271 */
272 public static MemberName make(Field field, boolean makeSetter) {
273 // Unreflected member names are resolved so intern them here.
274 MemberName tmp0 = null;
275 InternTransaction tx = new InternTransaction(field.getDeclaringClass());
276 while (tmp0 == null) {
277 MemberName tmp = new MemberName(field, makeSetter);
278 tmp0 = tx.tryIntern(tmp);
279 }
280 return tmp0;
281 }
282
283 /** Initialize a query. It is not resolved. */
284 private void init(Class<?> defClass, String name, Object type, int flags) {
285 // defining class is allowed to be null (for a naked name/type pair)
286 //name.toString(); // null check
287 //type.equals(type); // null check
288 // fill in fields:
289 this.clazz = defClass;
290 this.name = name;
291 this.type = type;
292 this.flags = flags;
293 assert(testAnyFlags(ALL_KINDS));
294 assert(this.resolution == null); // nobody should have touched this yet
295 //assert(referenceKindIsConsistent()); // do this after resolution
296 }
297
298 private void initResolved(boolean isResolved) {
299 assert(this.resolution == null); // not initialized yet!
300 if (!isResolved)
301 this.resolution = this;
302 assert(isResolved() == isResolved);
303 }
304
305 /**
306 * Helper method to intern this member name in the declaring class' member name table.
307 */
308 @SuppressWarnings("unchecked")
309 private MemberName intern(int transaction_token) {
310 return internMemberName(clazz, this, transaction_token);
311 }
312
313 /**
314 * Helper method to obtain the transaction token for interning, given Class clazz.
315 * @param clazz
316 * @return transaction token (class redefinition count)
317 */
318 static private int internTxnToken(Class clazz) {
319 return clazz == null ? 0 : jla.getClassRedefinedCount(clazz);
320 }
321
322 /**
323 * Helper method to obtain the transaction token for interning, given this.
324 * @return
325 */
326 private int internTxnToken() {
327 return internTxnToken(clazz);
328 }
329
330 /**
331 * Helper method to conditionally intern cloned+modified member names.
332 */
333 private MemberName intern(MemberName likeThis, int transaction_token) {
334 if (likeThis.isResolved())
335 return intern(transaction_token);
336 else
337 return this;
338 }
339
340 /**
341 * Helper class to handle the case where the class checked for no
342 * redefinition may not be correct; resolution can end up with a different
343 * class.
344 */
345 static class InternTransaction {
346 Class<?> tx_class;
347 int txn_token;
348
349 InternTransaction(Class<?> tx_class) {
350 this.tx_class = tx_class;
351 this.txn_token = internTxnToken(tx_class);
352 }
353
354 /**
355 * If member_name is not resolved, returns member_name; if is resolved,
356 * attempts to intern member_name (once) while checking for races.
357 *
358 * @param member_name
359 * @return member_name if not resolved, null if racing, otherwise
360 * value of interned member_name.
361 */
362 MemberName tryIntern(MemberName member_name) {
363 if (member_name.isResolved()) {
364 if (member_name.clazz != tx_class) {
365 Class prev_tx_class = tx_class;
366 int prev_txn_token = txn_token;
367 tx_class = member_name.clazz;
368 txn_token = internTxnToken(tx_class);
369 // Zero is a special case.
370 if (txn_token != 0 ||
371 prev_txn_token != internTxnToken(prev_tx_class)) {
372 // Resolved class is different and at least one
373 // redef of it occurred, therefore repeat with
374 // proper class for race consistency checking.
375 return null;
376 }
377 }
378 member_name = member_name.intern(txn_token);
379 if (member_name == null) {
380 // Update the token for the next try.
381 txn_token = internTxnToken(tx_class);
382 }
383 }
384 return member_name;
385 }
386 }
387
388 /** Return the declaring class of this member.
389 * In the case of a bare name and type, the declaring class will be null.
390 */
391 @Override
392 public Class<?> getDeclaringClass() {
393 return clazz;
394 }
395
396 /** Utility method producing the class loader of the declaring class. */
397 public ClassLoader getClassLoader() {
398 return clazz.getClassLoader();
399 }
400
401 /** Return the simple name of this member.
402 * For a type, it is the same as {@link Class#getSimpleName}.
403 * For a method or field, it is the simple name of the member.
404 * For a constructor, it is always {@code "<init>"}.
405 */
406 @Override
407 public String getName() {
408 if (name == null) {
409 expandFromVM();
410 if (name == null) {
411 return null;
412 }
413 }
414 return name;
415 }
416
417 public MethodType getMethodOrFieldType() {
418 if (isInvocable())
419 return getMethodType();
420 if (isGetter())
421 return MethodType.methodType(getFieldType());
422 if (isSetter())
423 return MethodType.methodType(void.class, getFieldType());
424 throw new InternalError("not a method or field: "+this);
425 }
426
532
533 /** Utility method to produce the signature of this member,
534 * used within the class file format to describe its type.
535 */
536 public String getSignature() {
537 if (type == null) {
538 expandFromVM();
539 if (type == null) {
540 return null;
541 }
542 }
543 if (isInvocable())
544 return BytecodeDescriptor.unparse(getMethodType());
545 else
546 return BytecodeDescriptor.unparse(getFieldType());
547 }
548
549 /** Return the modifier flags of this member.
550 * @see java.lang.reflect.Modifier
551 */
552 @Override
553 public int getModifiers() {
554 return (flags & RECOGNIZED_MODIFIERS);
555 }
556
557 /** Return the reference kind of this member, or zero if none.
558 */
559 public byte getReferenceKind() {
560 return (byte) ((flags >>> MN_REFERENCE_KIND_SHIFT) & MN_REFERENCE_KIND_MASK);
561 }
562 private boolean referenceKindIsConsistent() {
563 byte refKind = getReferenceKind();
564 if (refKind == REF_NONE) return isType();
565 if (isField()) {
566 assert(staticIsConsistent());
567 assert(MethodHandleNatives.refKindIsField(refKind));
568 } else if (isConstructor()) {
569 assert(refKind == REF_newInvokeSpecial || refKind == REF_invokeSpecial);
570 } else if (isMethod()) {
571 assert(staticIsConsistent());
572 assert(MethodHandleNatives.refKindIsMethod(refKind));
710 public boolean isNative() {
711 return Modifier.isNative(flags);
712 }
713 // let the rest (native, volatile, transient, etc.) be tested via Modifier.isFoo
714
715 // unofficial modifier flags, used by HotSpot:
716 static final int BRIDGE = 0x00000040;
717 static final int VARARGS = 0x00000080;
718 static final int SYNTHETIC = 0x00001000;
719 static final int ANNOTATION= 0x00002000;
720 static final int ENUM = 0x00004000;
721 /** Utility method to query the modifier flags of this member; returns false if the member is not a method. */
722 public boolean isBridge() {
723 return testAllFlags(IS_METHOD | BRIDGE);
724 }
725 /** Utility method to query the modifier flags of this member; returns false if the member is not a method. */
726 public boolean isVarargs() {
727 return testAllFlags(VARARGS) && isInvocable();
728 }
729 /** Utility method to query the modifier flags of this member; returns false if the member is not a method. */
730 @Override
731 public boolean isSynthetic() {
732 return testAllFlags(SYNTHETIC);
733 }
734
735 static final String CONSTRUCTOR_NAME = "<init>"; // the ever-popular
736
737 // modifiers exported by the JVM:
738 static final int RECOGNIZED_MODIFIERS = 0xFFFF;
739
740 // private flags, not part of RECOGNIZED_MODIFIERS:
741 static final int
742 IS_METHOD = MN_IS_METHOD, // method (not constructor)
743 IS_CONSTRUCTOR = MN_IS_CONSTRUCTOR, // constructor
744 IS_FIELD = MN_IS_FIELD, // field
745 IS_TYPE = MN_IS_TYPE, // nested type
746 CALLER_SENSITIVE = MN_CALLER_SENSITIVE; // @CallerSensitive annotation detected
747
748 static final int ALL_ACCESS = Modifier.PUBLIC | Modifier.PRIVATE | Modifier.PROTECTED;
749 static final int ALL_KINDS = IS_METHOD | IS_CONSTRUCTOR | IS_FIELD | IS_TYPE;
750 static final int IS_INVOCABLE = IS_METHOD | IS_CONSTRUCTOR;
773 }
774 /** Query whether this member is a type. */
775 public boolean isType() {
776 return testAllFlags(IS_TYPE);
777 }
778 /** Utility method to query whether this member is neither public, private, nor protected. */
779 public boolean isPackage() {
780 return !testAnyFlags(ALL_ACCESS);
781 }
782 /** Query whether this member has a CallerSensitive annotation. */
783 public boolean isCallerSensitive() {
784 return testAllFlags(CALLER_SENSITIVE);
785 }
786
787 /** Utility method to query whether this member is accessible from a given lookup class. */
788 public boolean isAccessibleFrom(Class<?> lookupClass) {
789 return VerifyAccess.isMemberAccessible(this.getDeclaringClass(), this.getDeclaringClass(), flags,
790 lookupClass, ALL_ACCESS|MethodHandles.Lookup.PACKAGE);
791 }
792
793 /**
794 * Calls down to the VM to fill in the fields. This method is
795 * synchronized to avoid racing calls.
796 */
797 private void expandFromVM() {
798 if (type != null) {
799 return;
800 }
801 if (!isResolved()) {
802 return;
803 }
804 MethodHandleNatives.expand(this);
805 }
806
807 // Capturing information from the Core Reflection API:
808 private static int flagsMods(int flags, int mods, byte refKind) {
809 assert((flags & RECOGNIZED_MODIFIERS) == 0);
810 assert((mods & ~RECOGNIZED_MODIFIERS) == 0);
811 assert((refKind & ~MN_REFERENCE_KIND_MASK) == 0);
812 return flags | mods | (refKind << MN_REFERENCE_KIND_SHIFT);
813 }
814
815 public MemberName asSpecial() {
816 switch (getReferenceKind()) {
817 case REF_invokeSpecial: return this;
818 case REF_invokeVirtual: return cloneAndChangeReferenceKindAndIntern(REF_invokeSpecial, REF_invokeVirtual);
819 case REF_invokeInterface: return cloneAndChangeReferenceKindAndIntern(REF_invokeSpecial, REF_invokeInterface);
820 case REF_newInvokeSpecial: return cloneAndChangeReferenceKindAndIntern(REF_invokeSpecial, REF_newInvokeSpecial);
821 }
822 throw new IllegalArgumentException(this.toString());
823 }
824 /** If this MN is not REF_newInvokeSpecial, return a clone with that ref. kind.
825 * In that case it must already be REF_invokeSpecial.
826 */
827 public MemberName asConstructor() {
828 switch (getReferenceKind()) {
829 case REF_invokeSpecial: return cloneAndChangeReferenceKindAndIntern(REF_newInvokeSpecial, REF_invokeSpecial);
830 case REF_newInvokeSpecial: return this;
831 }
832 throw new IllegalArgumentException(this.toString());
833 }
834 /** If this MN is a REF_invokeSpecial, return a clone with the "normal" kind
835 * REF_invokeVirtual; also switch either to REF_invokeInterface if clazz.isInterface.
836 * The end result is to get a fully virtualized version of the MN.
837 * (Note that resolving in the JVM will sometimes devirtualize, changing
838 * REF_invokeVirtual of a final to REF_invokeSpecial, and REF_invokeInterface
839 * in some corner cases to either of the previous two; this transform
840 * undoes that change under the assumption that it occurred.)
841 */
842 public MemberName asNormalOriginal() {
843 byte normalVirtual = clazz.isInterface() ? REF_invokeInterface : REF_invokeVirtual;
844 byte refKind = getReferenceKind();
845 byte newRefKind = refKind;
846 MemberName result = this;
847 switch (refKind) {
848 case REF_invokeInterface:
849 case REF_invokeVirtual:
850 case REF_invokeSpecial:
851 newRefKind = normalVirtual;
852 break;
853 }
854 if (newRefKind == refKind)
855 return this;
856 result = cloneAndChangeReferenceKindAndIntern(newRefKind, refKind);
857 assert(this.referenceKindIsConsistentWith(result.getReferenceKind()));
858 return result;
859 }
860
861 /**
862 * Clones, changes reference kind in the clone, and if this is resolved,
863 * also interns the result, repeating the intern operation till it succeeds.
864 *
865 * @param refKind
866 * @param oldKind
867 * @return
868 */
869 private MemberName cloneAndChangeReferenceKindAndIntern(byte refKind, byte oldKind) {
870 MemberName tmp0 = null;
871 while (tmp0 == null) {
872 int tx_token = internTxnToken(); // this and clone will have same token
873 tmp0 = clone().changeReferenceKind(refKind, oldKind).intern(this, tx_token);
874 }
875 return tmp0;
876 }
877
878 public boolean isGetter() {
879 return MethodHandleNatives.refKindIsGetter(getReferenceKind());
880 }
881 public boolean isSetter() {
882 return MethodHandleNatives.refKindIsSetter(getReferenceKind());
883 }
884 public MemberName asSetter() {
885 byte refKind = getReferenceKind();
886 assert(MethodHandleNatives.refKindIsGetter(refKind));
887 assert((REF_putStatic - REF_getStatic) == (REF_putField - REF_getField));
888 byte setterRefKind = (byte)(refKind + (REF_putField - REF_getField));
889 return cloneAndChangeReferenceKindAndIntern(setterRefKind, refKind);
890 }
891 /**
892 * Create a name for a signature-polymorphic invoker.
893 * This is a placeholder for a signature-polymorphic instance
894 * (of MH.invokeExact, etc.) that the JVM does not reify.
895 * The returned MemberName is not resolved.
896 * See comments on {@link MethodHandleNatives#linkMethod}.
897 */
898 static MemberName makeMethodHandleInvoke(String name, MethodType type) {
899 return makeMethodHandleInvoke(name, type, MH_INVOKE_MODS | SYNTHETIC);
900 }
901 static MemberName makeMethodHandleInvoke(String name, MethodType type, int mods) {
902 MemberName mem = new MemberName(MethodHandle.class, name, type, REF_invokeVirtual);
903 mem.flags |= mods; // it's not resolved, but add these modifiers anyway
904 assert(mem.isMethodHandleInvoke()) : mem;
905 return mem;
906 }
907
908 // locally useful cloner
909 @Override protected MemberName clone() {
910 try {
911 return (MemberName) super.clone();
912 } catch (CloneNotSupportedException ex) {
913 throw newInternalError(ex);
914 }
915 }
916
917 /** Get the definition of this member name.
918 * This may be in a super-class of the declaring class of this member.
919 */
920 public MemberName getDefinition() {
921 if (!isResolved()) throw new IllegalStateException("must be resolved: "+this);
922 if (isType()) return this;
923 MemberName res = this.clone();
924 res.clazz = null;
925 res.type = null;
926 res.name = null;
927 res.resolution = res;
936 }
937 @Override
938 public boolean equals(Object that) {
939 return (that instanceof MemberName && this.equals((MemberName)that));
940 }
941
942 /** Decide if two member names have exactly the same symbolic content.
943 * Does not take into account any actual class members, so even if
944 * two member names resolve to the same actual member, they may
945 * be distinct references.
946 */
947 public boolean equals(MemberName that) {
948 if (this == that) return true;
949 if (that == null) return false;
950 return this.clazz == that.clazz
951 && this.getReferenceKind() == that.getReferenceKind()
952 && Objects.equals(this.name, that.name)
953 && Objects.equals(this.getType(), that.getType());
954 }
955
956 @Override
957 public int compareTo(Object o) {
958 MemberName that = (MemberName) o;
959
960 /* First test equals. This make the ordering checks easier because we
961 * don't have to be precise and can use hash codes.
962 */
963 if (equals(that)) {
964 return 0;
965 }
966
967 int diff = Integer.compare(this.name.hashCode(), that.name.hashCode());
968 if (diff != 0) {
969 return diff;
970 }
971
972 diff = this.getReferenceKind() - that.getReferenceKind();
973 if (diff != 0) {
974 return diff;
975 }
976
977 diff = Integer.compare(this.getType().hashCode(), that.getType().hashCode());
978 if (diff != 0) {
979 return diff;
980 }
981
982 // Hashcodes apparently collided, try more detail.
983 diff = this.name.compareTo(that.name);
984 if (diff != 0) {
985 return diff;
986 }
987
988 // The classes ought to all be equal anyway in the usual use of
989 // compareTo, so check these later,
990 // but before comparing getType.toString().
991 diff = Integer.compare(this.clazz.hashCode(),that.clazz.hashCode());
992 if (diff != 0) {
993 return diff;
994 }
995
996 diff = this.clazz.getName().compareTo(that.clazz.getName());
997 if (diff != 0) {
998 return diff;
999 }
1000
1001 diff = this.getType().toString().compareTo(that.getType().toString());
1002 if (diff != 0) {
1003 return diff;
1004 }
1005
1006 // Nothing left but classLoaders.
1007 ClassLoader thisCl = this.getClassLoader();
1008 ClassLoader thatCl = that.getClassLoader();
1009
1010 if (thisCl == thatCl) return 0;
1011
1012 diff = Integer.compare(thisCl == null ? 0 : thisCl.hashCode(),
1013 thatCl == null ? 0 : thatCl.hashCode());
1014
1015 return diff;
1016 }
1017
1018 /** Query whether this member name is resolved to a non-static, non-final method.
1019 */
1020 public boolean hasReceiverTypeDispatch() {
1021 return MethodHandleNatives.refKindDoesDispatch(getReferenceKind());
1022 }
1023
1024 /** Query whether this member name is resolved.
1025 * A resolved member name is one for which the JVM has found
1026 * a method, constructor, field, or type binding corresponding exactly to the name.
1027 * (Document?)
1028 */
1029 public boolean isResolved() {
1030 return resolution == null;
1031 }
1032
1033 void checkForTypeAlias() {
1034 if (isInvocable()) {
1035 MethodType type;
1036 if (this.type instanceof MethodType)
1037 type = (MethodType) this.type;
1038 else
1039 this.type = type = getMethodType();
1040 if (type.erase() == type) return;
1041 if (VerifyAccess.isTypeVisible(type, clazz)) return;
1042 throw new LinkageError("bad method type alias: "+type+" not visible from "+clazz);
1043 } else {
1044 Class<?> type;
1045 if (this.type instanceof Class<?>)
1046 type = (Class<?>) this.type;
1047 else
1048 this.type = type = getFieldType();
1049 if (VerifyAccess.isTypeVisible(type, clazz)) return;
1050 throw new LinkageError("bad field type alias: "+type+" not visible from "+clazz);
1051 }
1052 }
1119 else if (isMethod())
1120 ex = new NoSuchMethodException(message);
1121 else
1122 ex = new NoSuchFieldException(message);
1123 if (resolution instanceof Throwable)
1124 ex.initCause((Throwable) resolution);
1125 return ex;
1126 }
1127
1128 /** Actually making a query requires an access check. */
1129 /*non-public*/ static Factory getFactory() {
1130 return Factory.INSTANCE;
1131 }
1132 /** A factory type for resolving member names with the help of the VM.
1133 * TBD: Define access-safe public constructors for this factory.
1134 */
1135 /*non-public*/ static class Factory {
1136 private Factory() { } // singleton pattern
1137 static Factory INSTANCE = new Factory();
1138
1139 private final static int ALLOWED_FLAGS = ALL_KINDS;
1140
1141 /// Queries
1142 List<MemberName> getMembers(Class<?> defc,
1143 String matchName, Object matchType,
1144 int matchFlags, Class<?> lookupClass) {
1145 matchFlags &= ALLOWED_FLAGS;
1146 String matchSig = null;
1147 if (matchType != null) {
1148 matchSig = BytecodeDescriptor.unparse(matchType);
1149 if (matchSig.startsWith("("))
1150 matchFlags &= ~(ALL_KINDS & ~IS_INVOCABLE);
1151 else
1152 matchFlags &= ~(ALL_KINDS & ~IS_FIELD);
1153 }
1154 final int BUF_MAX = 0x2000;
1155 int len1 = matchName == null ? 10 : matchType == null ? 4 : 1;
1156 MemberName[] buf = newMemberBuffer(len1);
1157 int totalCount = 0;
1158 ArrayList<MemberName[]> bufs = null;
1159 int bufCount = 0;
1185 }
1186 result.addAll(Arrays.asList(buf).subList(0, bufCount));
1187 // Signature matching is not the same as type matching, since
1188 // one signature might correspond to several types.
1189 // So if matchType is a Class or MethodType, refilter the results.
1190 if (matchType != null && matchType != matchSig) {
1191 for (Iterator<MemberName> it = result.iterator(); it.hasNext();) {
1192 MemberName m = it.next();
1193 if (!matchType.equals(m.getType()))
1194 it.remove();
1195 }
1196 }
1197 return result;
1198 }
1199 /** Produce a resolved version of the given member.
1200 * Super types are searched (for inherited members) if {@code searchSupers} is true.
1201 * Access checking is performed on behalf of the given {@code lookupClass}.
1202 * If lookup fails or access is not permitted, null is returned.
1203 * Otherwise a fresh copy of the given member is returned, with modifier bits filled in.
1204 */
1205 private static MemberName resolve(byte refKind, MemberName ref, Class<?> lookupClass) {
1206 MemberName m = ref.clone(); // JVM will side-effect the ref
1207 assert(refKind == m.getReferenceKind());
1208 try {
1209 m = MethodHandleNatives.resolve(m, lookupClass);
1210 m.checkForTypeAlias();
1211 m.resolution = null;
1212 } catch (LinkageError ex) {
1213 // JVM reports that the "bytecode behavior" would get an error
1214 assert(!m.isResolved());
1215 m.resolution = ex;
1216 return m;
1217 }
1218 assert(m.referenceKindIsConsistent());
1219 m.initResolved(true);
1220 assert(m.vminfoIsConsistent());
1221 // m = m.intern(); // do not intern -- caller should intern instead.
1222 return m;
1223 }
1224 /** Produce a resolved version of the given member.
1225 * Super types are searched (for inherited members) if {@code searchSupers} is true.
1226 * Access checking is performed on behalf of the given {@code lookupClass}.
1227 * If lookup fails or access is not permitted, a {@linkplain ReflectiveOperationException} is thrown.
1228 * Otherwise the given member or its interned copy is returned, with modifier bits filled in.
1229 */
1230 public
1231 <NoSuchMemberException extends ReflectiveOperationException>
1232 MemberName resolveOrFail(byte refKind, MemberName m, Class<?> lookupClass,
1233 Class<NoSuchMemberException> nsmClass)
1234 throws IllegalAccessException, NoSuchMemberException {
1235 MemberName result = resolveOrNot(refKind, m, lookupClass);
1236
1237 if (result.isResolved()) {
1238 return result;
1239 } else { // not resolved, throw exception
1240 ReflectiveOperationException ex = result.makeAccessException();
1241 if (ex instanceof IllegalAccessException) {
1242 throw (IllegalAccessException) ex;
1243 }
1244 throw nsmClass.cast(ex);
1245 }
1246 }
1247 /** Produce a resolved version of the given member.
1248 * Super types are searched (for inherited members) if {@code searchSupers} is true.
1249 * Access checking is performed on behalf of the given {@code lookupClass}.
1250 * If lookup fails or access is not permitted, return null.
1251 * Otherwise the given member or its interned copy is returned, with modifier bits filled in.
1252 */
1253 public
1254 MemberName resolveOrNull(byte refKind, MemberName m, Class<?> lookupClass) {
1255 MemberName result = resolveOrNot(refKind, m, lookupClass);
1256 return result.isResolved() ? result : null;
1257 }
1258
1259 private static
1260 MemberName resolveOrNot(byte refKind, MemberName m, Class<?> lookupClass) {
1261 MemberName result = null;
1262 Class tx_class = m.clazz; // Guess a class for race detection.
1263 while (result == null) { // iterate till no race.
1264 int txn_token = internTxnToken(tx_class);
1265
1266 MemberName result0 = resolve(refKind, m, lookupClass);
1267
1268 if (result0.isResolved()) {
1269 if (result0.clazz != tx_class) { // Confirm/correct guess
1270 Class prev_tx_class = tx_class;
1271 int prev_txn_token = txn_token;
1272 tx_class = result0.clazz;
1273 txn_token = internTxnToken(tx_class);
1274 // The guess may be good enough
1275 if (txn_token != 0 ||
1276 prev_txn_token != internTxnToken(prev_tx_class)) {
1277 // Resolved class is different and at least one
1278 // redef occurred, therefore repeat with
1279 // proper class for race consistency checking.
1280 continue;
1281 }
1282 }
1283 result = result0.intern(txn_token);
1284 } else { // Resolution failed, do not intern, return unresolved MemberName
1285 return result0;
1286 }
1287 }
1288 return result;
1289 }
1290
1291 /** Return a list of all methods defined by the given class.
1292 * Super types are searched (for inherited members) if {@code searchSupers} is true.
1293 * Access checking is performed on behalf of the given {@code lookupClass}.
1294 * Inaccessible members are not added to the last.
1295 */
1296 public List<MemberName> getMethods(Class<?> defc, boolean searchSupers,
1297 Class<?> lookupClass) {
1298 return getMethods(defc, searchSupers, null, null, lookupClass);
1299 }
1300 /** Return a list of matching methods defined by the given class.
1301 * Super types are searched (for inherited members) if {@code searchSupers} is true.
1302 * Returned methods will match the name (if not null) and the type (if not null).
1303 * Access checking is performed on behalf of the given {@code lookupClass}.
1304 * Inaccessible members are not added to the last.
1305 */
1306 public List<MemberName> getMethods(Class<?> defc, boolean searchSupers,
1307 String name, MethodType type, Class<?> lookupClass) {
1308 int matchFlags = IS_METHOD | (searchSupers ? SEARCH_ALL_SUPERS : 0);
1309 return getMembers(defc, name, type, matchFlags, lookupClass);
1310 }
1337 }
1338 /** Return a list of all nested types defined by the given class.
1339 * Super types are searched (for inherited members) if {@code searchSupers} is true.
1340 * Access checking is performed on behalf of the given {@code lookupClass}.
1341 * Inaccessible members are not added to the last.
1342 */
1343 public List<MemberName> getNestedTypes(Class<?> defc, boolean searchSupers,
1344 Class<?> lookupClass) {
1345 int matchFlags = IS_TYPE | (searchSupers ? SEARCH_ALL_SUPERS : 0);
1346 return getMembers(defc, null, null, matchFlags, lookupClass);
1347 }
1348 private static MemberName[] newMemberBuffer(int length) {
1349 MemberName[] buf = new MemberName[length];
1350 // fill the buffer with dummy structs for the JVM to fill in
1351 for (int i = 0; i < length; i++)
1352 buf[i] = new MemberName();
1353 return buf;
1354 }
1355 }
1356
1357
1358 /**
1359 * Lazily create {@link ClassData}.
1360 */
1361 /* package */ static ClassData classData(Class<?> klazz) {
1362 if (jla.getClassData(klazz) == null) {
1363 jla.casClassData(klazz, null, new ClassData());
1364 }
1365 return (ClassData) jla.getClassData(klazz);
1366 }
1367
1368 /* package */ static MemberName internMemberName(Class<?> klazz, MemberName memberName, int redefined_count) {
1369 return classData(klazz).intern(klazz, memberName, redefined_count);
1370 }
1371
1372 /**
1373 * ClassData
1374 */
1375 private static class ClassData {
1376 /**
1377 * This needs to be a simple data structure because we need to access
1378 * and update its elements from the JVM. Note that the Java side controls
1379 * the allocation and order of elements in the array; the JVM modifies
1380 * fields of those elements during class redefinition.
1381 */
1382 private volatile MemberName[] elementData;
1383 private volatile MemberName publishedToVM;
1384 private volatile int size;
1385
1386 /**
1387 * Interns a member name in the member name table.
1388 * Returns null if a race with the jvm occurred. Races are detected
1389 * by checking for changes in the class redefinition count that occur
1390 * before an intern is complete.
1391 *
1392 * @param klass class whose redefinition count is checked.
1393 * @param memberName member name to be interned
1394 * @param redefined_count the value of classRedefinedCount() observed before
1395 * creation of the MemberName that is being interned.
1396 * @return null if a race occurred, otherwise the interned MemberName.
1397 */
1398 @SuppressWarnings({"unchecked","rawtypes"})
1399 public MemberName intern(Class<?> klass, MemberName memberName, int redefined_count) {
1400 if (elementData == null) {
1401 synchronized (this) {
1402 if (elementData == null) {
1403 elementData = new MemberName[1];
1404 }
1405 }
1406 }
1407 synchronized (this) { // this == ClassData
1408 final int index = Arrays.binarySearch(elementData, 0, size, memberName);
1409 if (index >= 0) {
1410 return elementData[index];
1411 }
1412 // Not found, add carefully.
1413 return add(klass, ~index, memberName, redefined_count);
1414 }
1415 }
1416
1417 /**
1418 * Appends the specified element at the specified index.
1419 *
1420 * @param klass the klass for this ClassData.
1421 * @param index index at which insertion should occur
1422 * @param e element to be insert into this list
1423 * @param redefined_count value of klass.classRedefinedCount() before e was created.
1424 * @return null if insertion failed because of redefinition race, otherwise e.
1425 */
1426 private MemberName add(Class<?> klass, int index, MemberName e, int redefined_count) {
1427 // First attempt publication to JVM, if that succeeds,
1428 // then record internally.
1429 e.next = publishedToVM;
1430 publishedToVM = e;
1431 storeFence();
1432 if (redefined_count != jla.getClassRedefinedCount(klass)) {
1433 // Lost a race, back out publication and report failure.
1434 publishedToVM = e.next;
1435 return null;
1436 }
1437
1438 int oldSize = size;
1439 MemberName[] element_data = elementData;
1440 if (oldSize + 1 > element_data.length ) {
1441 grow(oldSize + 1);
1442 element_data = elementData;
1443 }
1444
1445 if (oldSize > 0) {
1446 for (int i = oldSize; i > index; i--) {
1447 // pre: element_data[i] is duplicated at [i+1]
1448 element_data[i] = element_data[i - 1];
1449 // post: element_data[i-1] is duplicated at [i]
1450 }
1451 // element_data[index] is duplicated at [index+1]
1452 }
1453 element_data[index] = e;
1454 size += 1;
1455 return e;
1456 }
1457
1458 /**
1459 * Increases the capacity to ensure that it can hold at least the
1460 * number of elements specified by the minimum capacity argument.
1461 *
1462 * @param minCapacity the desired minimum capacity
1463 */
1464 private void grow(int minCapacity) {
1465 // overflow-conscious code
1466 int oldCapacity = elementData.length;
1467 int newCapacity = oldCapacity + (oldCapacity >> 1);
1468 if (newCapacity - minCapacity < 0)
1469 newCapacity = minCapacity;
1470 // minCapacity is usually close to size, so this is a win:
1471 elementData = Arrays.copyOf(elementData, newCapacity);
1472 }
1473 }
1474 }
|