src/java.base/share/classes/java/lang/invoke/MemberName.java
Index Unified diffs Context diffs Sdiffs Patch New Old Previous File Next File jdk Cdiff src/java.base/share/classes/java/lang/invoke/MemberName.java

src/java.base/share/classes/java/lang/invoke/MemberName.java

Print this page

        

*** 1,7 **** /* ! * Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this --- 1,7 ---- /* ! * Copyright (c) 2008, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this
*** 36,47 **** --- 36,52 ---- import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.Iterator; import java.util.List; + import static java.lang.invoke.MethodHandleNatives.Constants.*; import static java.lang.invoke.MethodHandleStatics.*; + + import sun.misc.JavaLangAccess; + import sun.misc.SharedSecrets; + import java.util.Objects; /** * A {@code MemberName} is a compact symbolic datum which fully characterizes * a method or field reference.
*** 67,88 **** * allows invocation. A MemberName is much lighter than a Method, * since it contains about 7 fields to the 16 of Method (plus its sub-arrays), * and those seven fields omit much of the information in Method. * @author jrose */ ! /*non-public*/ final class MemberName implements Member, Cloneable { private Class<?> clazz; // class in which the method is defined private String name; // may be null if not yet materialized private Object type; // may be null if not yet materialized private int flags; // modifier bits; see reflect.Modifier //@Injected JVM_Method* vmtarget; //@Injected int vmindex; private Object resolution; // if null, this guy is resolved /** Return the declaring class of this member. * In the case of a bare name and type, the declaring class will be null. */ public Class<?> getDeclaringClass() { return clazz; } /** Utility method producing the class loader of the declaring class. */ --- 72,382 ---- * allows invocation. A MemberName is much lighter than a Method, * since it contains about 7 fields to the 16 of Method (plus its sub-arrays), * and those seven fields omit much of the information in Method. * @author jrose */ ! @SuppressWarnings("rawtypes") //Comparable in next line ! /*non-public*/ final class MemberName implements Member, Comparable, Cloneable { private Class<?> clazz; // class in which the method is defined private String name; // may be null if not yet materialized private Object type; // may be null if not yet materialized private int flags; // modifier bits; see reflect.Modifier //@Injected JVM_Method* vmtarget; //@Injected int vmindex; private Object resolution; // if null, this guy is resolved + private static final JavaLangAccess jla = SharedSecrets.getJavaLangAccess(); + + // bare-bones constructor; the JVM will fill it in + MemberName() { } + + /** Create a name for the given class. The resulting name will be in a resolved state. */ + public MemberName(Class<?> type) { + init(type.getDeclaringClass(), type.getSimpleName(), type, + flagsMods(IS_TYPE, type.getModifiers(), REF_NONE)); + initResolved(true); + } + + // Construction from symbolic parts, for queries: + /** Create a field or type name from the given components: + * Declaring class, name, type, reference kind. + * The declaring class may be supplied as null if this is to be a bare name and type. + * The resulting name will in an unresolved state. + */ + public MemberName(Class<?> defClass, String name, Class<?> type, byte refKind) { + init(defClass, name, type, flagsMods(IS_FIELD, 0, refKind)); + initResolved(false); + } + + /** Create a field or type name from the given components: Declaring class, name, type. + * The declaring class may be supplied as null if this is to be a bare name and type. + * The modifier flags default to zero. + * The resulting name will in an unresolved state. + */ + public MemberName(Class<?> defClass, String name, Class<?> type, Void unused) { + this(defClass, name, type, REF_NONE); + initResolved(false); + } + + /** Create a method or constructor name from the given components: Declaring class, name, type, modifiers. + * It will be a constructor if and only if the name is {@code "&lt;init&gt;"}. + * The declaring class may be supplied as null if this is to be a bare name and type. + * The last argument is optional, a boolean which requests REF_invokeSpecial. + * The resulting name will in an unresolved state. + */ + public MemberName(Class<?> defClass, String name, MethodType type, byte refKind) { + int initFlags = (name != null && name.equals(CONSTRUCTOR_NAME) ? IS_CONSTRUCTOR : IS_METHOD); + init(defClass, name, type, flagsMods(initFlags, 0, refKind)); + initResolved(false); + } + + /** Create a method, constructor, or field name from the given components: + * Reference kind, declaring class, name, type. + */ + public MemberName(byte refKind, Class<?> defClass, String name, Object type) { + int kindFlags; + if (MethodHandleNatives.refKindIsField(refKind)) { + kindFlags = IS_FIELD; + if (!(type instanceof Class)) + throw newIllegalArgumentException("not a field type"); + } else if (MethodHandleNatives.refKindIsMethod(refKind)) { + kindFlags = IS_METHOD; + if (!(type instanceof MethodType)) + throw newIllegalArgumentException("not a method type"); + } else if (refKind == REF_newInvokeSpecial) { + kindFlags = IS_CONSTRUCTOR; + if (!(type instanceof MethodType) || + !CONSTRUCTOR_NAME.equals(name)) + throw newIllegalArgumentException("not a constructor type or name"); + } else { + throw newIllegalArgumentException("bad reference kind "+refKind); + } + init(defClass, name, type, flagsMods(kindFlags, 0, refKind)); + initResolved(false); + } + + /** Create a name for the given reflected method. The resulting name will be in a resolved state. */ + public static MemberName make(Method m) { + return make(m, false); + } + + @SuppressWarnings("LeakingThisInConstructor") + private MemberName(Method m, boolean wantSpecial) { + m.getClass(); // NPE check + // fill in vmtarget, vmindex while we have m in hand: + MethodHandleNatives.init(this, m); + if (clazz == null) { // MHN.init failed + if (m.getDeclaringClass() == MethodHandle.class && + isMethodHandleInvokeName(m.getName())) { + // The JVM did not reify this signature-polymorphic instance. + // Need a special case here. + // See comments on MethodHandleNatives.linkMethod. + MethodType type = MethodType.methodType(m.getReturnType(), m.getParameterTypes()); + int flags = flagsMods(IS_METHOD, m.getModifiers(), REF_invokeVirtual); + init(MethodHandle.class, m.getName(), type, flags); + if (isMethodHandleInvoke()) { + return; + } + } + throw new LinkageError(m.toString()); + } + assert(isResolved() && this.clazz != null); + this.name = m.getName(); + if (this.type == null) { + this.type = new Object[] { m.getReturnType(), m.getParameterTypes() }; + } + if (wantSpecial) { + if (isAbstract()) { + throw new AbstractMethodError(this.toString()); + } + if (getReferenceKind() == REF_invokeVirtual) { + changeReferenceKind(REF_invokeSpecial, REF_invokeVirtual); + } else if (getReferenceKind() == REF_invokeInterface) { + // invokeSpecial on a default method + changeReferenceKind(REF_invokeSpecial, REF_invokeInterface); + } + } + } + + public static MemberName make(Method m, boolean wantSpecial) { + // Unreflected member names are resolved so intern them here. + MemberName tmp0 = null; + InternTransaction tx = new InternTransaction(m.getDeclaringClass()); + while (tmp0 == null) { + MemberName tmp = new MemberName(m, wantSpecial); + tmp0 = tx.tryIntern(tmp); + } + return tmp0; + } + + /** + * Create a name for the given reflected constructor. The resulting name + * will be in a resolved state. + */ + @SuppressWarnings("LeakingThisInConstructor") + private MemberName(Constructor<?> ctor) { + ctor.getClass(); // NPE check + // fill in vmtarget, vmindex while we have ctor in hand: + MethodHandleNatives.init(this, ctor); + assert(isResolved() && this.clazz != null); + this.name = CONSTRUCTOR_NAME; + if (this.type == null) { + this.type = new Object[] { void.class, ctor.getParameterTypes() }; + } + } + + public static MemberName make(Constructor<?> ctor) { + // Unreflected member names are resolved so intern them here. + MemberName tmp0 = null; + InternTransaction tx = new InternTransaction(ctor.getDeclaringClass()); + while (tmp0 == null) { + MemberName tmp = new MemberName(ctor); + tmp0 = tx.tryIntern(tmp); + } + return tmp0; + } + + /** Create a name for the given reflected field. The resulting name will be in a resolved state. + */ + public static MemberName make(Field field) { + return make(field, false); + } + + @SuppressWarnings("LeakingThisInConstructor") + private MemberName(Field field, boolean makeSetter) { + field.getClass(); // NPE check + // fill in vmtarget, vmindex while we have field in hand: + MethodHandleNatives.init(this, field); + assert(isResolved() && this.clazz != null); + this.name = field.getName(); + this.type = field.getType(); + byte refKind = this.getReferenceKind(); + assert(refKind == (isStatic() ? REF_getStatic : REF_getField)); + if (makeSetter) { + assert((REF_putStatic - REF_getStatic) == (REF_putField - REF_getField)); + changeReferenceKind((byte)(refKind + (REF_putStatic - REF_getStatic)), refKind); + } + } + + public static MemberName make(Field field, boolean makeSetter) { + // Unreflected member names are resolved so intern them here. + MemberName tmp0 = null; + InternTransaction tx = new InternTransaction(field.getDeclaringClass()); + while (tmp0 == null) { + MemberName tmp = new MemberName(field, makeSetter); + tmp0 = tx.tryIntern(tmp); + } + return tmp0; + } + + /** Initialize a query. It is not resolved. */ + private void init(Class<?> defClass, String name, Object type, int flags) { + // defining class is allowed to be null (for a naked name/type pair) + //name.toString(); // null check + //type.equals(type); // null check + // fill in fields: + this.clazz = defClass; + this.name = name; + this.type = type; + this.flags = flags; + assert(testAnyFlags(ALL_KINDS)); + assert(this.resolution == null); // nobody should have touched this yet + //assert(referenceKindIsConsistent()); // do this after resolution + } + + private void initResolved(boolean isResolved) { + assert(this.resolution == null); // not initialized yet! + if (!isResolved) + this.resolution = this; + assert(isResolved() == isResolved); + } + + /** + * Helper method to intern this member name in the declaring class' member name table. + */ + @SuppressWarnings("unchecked") + private MemberName intern(int transaction_token) { + return jla.internMemberName(clazz, this, transaction_token); + } + + /** + * Helper method to obtain the transaction token for interning, + * given Class clazz. + * @param clazz + * @return + */ + static private int internTxnToken(Class clazz) { + return clazz == null ? 0 : jla.getClassRedefinedCount(clazz); + } + + /** + * Helper method to obtain the transaction token for interning, given this. + * @return + */ + private int internTxnToken() { + return internTxnToken(clazz); + } + + /** + * Helper method to conditionally intern cloned+modified member names. + */ + private MemberName intern(MemberName likeThis, int transaction_token) { + if (likeThis.isResolved()) + return intern(transaction_token); + else + return this; + } + + /** + * Helper class to handle the case where the class checked for no + * redefinition may not be correct; resolution can end up with a different + * class. + */ + static class InternTransaction { + Class<?> tx_class; + int txn_token; + + InternTransaction(Class<?> tx_class) { + this.tx_class = tx_class; + this.txn_token = internTxnToken(tx_class); + } + + /** + * If member_name is not resolved, returns member_name; if is resolved, + * attempts to intern member_name (once) while checking for races. + * + * @param member_name + * @return member_name if not resolved, null if racing, otherwise + * value of interned member_name. + */ + MemberName tryIntern(MemberName member_name) { + if (member_name.isResolved()) { + if (member_name.getClass() != tx_class) { + Class prev_tx_class = tx_class; + int prev_txn_token = txn_token; + tx_class = member_name.getClass(); + txn_token = internTxnToken(tx_class); + // Zero is a special case. + if (txn_token != 0 || + prev_txn_token != internTxnToken(prev_tx_class)) { + // Resolved class is different and at least one + // redef of it occurred, therefore repeat with + // proper class for race consistency checking. + return null; + } + } + return member_name.intern(txn_token); + } else { + return member_name; + } + } + } + /** Return the declaring class of this member. * In the case of a bare name and type, the declaring class will be null. */ + @Override public Class<?> getDeclaringClass() { return clazz; } /** Utility method producing the class loader of the declaring class. */
*** 93,102 **** --- 387,397 ---- /** Return the simple name of this member. * For a type, it is the same as {@link Class#getSimpleName}. * For a method or field, it is the simple name of the member. * For a constructor, it is always {@code "&lt;init&gt;"}. */ + @Override public String getName() { if (name == null) { expandFromVM(); if (name == null) { return null;
*** 238,247 **** --- 533,543 ---- } /** Return the modifier flags of this member. * @see java.lang.reflect.Modifier */ + @Override public int getModifiers() { return (flags & RECOGNIZED_MODIFIERS); } /** Return the reference kind of this member, or zero if none.
*** 415,424 **** --- 711,721 ---- /** Utility method to query the modifier flags of this member; returns false if the member is not a method. */ public boolean isVarargs() { return testAllFlags(VARARGS) && isInvocable(); } /** Utility method to query the modifier flags of this member; returns false if the member is not a method. */ + @Override public boolean isSynthetic() { return testAllFlags(SYNTHETIC); } static final String CONSTRUCTOR_NAME = "<init>"; // the ever-popular
*** 477,501 **** public boolean isAccessibleFrom(Class<?> lookupClass) { return VerifyAccess.isMemberAccessible(this.getDeclaringClass(), this.getDeclaringClass(), flags, lookupClass, ALL_ACCESS|MethodHandles.Lookup.PACKAGE); } - /** Initialize a query. It is not resolved. */ - private void init(Class<?> defClass, String name, Object type, int flags) { - // defining class is allowed to be null (for a naked name/type pair) - //name.toString(); // null check - //type.equals(type); // null check - // fill in fields: - this.clazz = defClass; - this.name = name; - this.type = type; - this.flags = flags; - assert(testAnyFlags(ALL_KINDS)); - assert(this.resolution == null); // nobody should have touched this yet - //assert(referenceKindIsConsistent()); // do this after resolution - } - /** * Calls down to the VM to fill in the fields. This method is * synchronized to avoid racing calls. */ private void expandFromVM() { --- 774,783 ----
*** 513,574 **** assert((flags & RECOGNIZED_MODIFIERS) == 0); assert((mods & ~RECOGNIZED_MODIFIERS) == 0); assert((refKind & ~MN_REFERENCE_KIND_MASK) == 0); return flags | mods | (refKind << MN_REFERENCE_KIND_SHIFT); } ! /** Create a name for the given reflected method. The resulting name will be in a resolved state. */ ! public MemberName(Method m) { ! this(m, false); ! } ! @SuppressWarnings("LeakingThisInConstructor") ! public MemberName(Method m, boolean wantSpecial) { ! m.getClass(); // NPE check ! // fill in vmtarget, vmindex while we have m in hand: ! MethodHandleNatives.init(this, m); ! if (clazz == null) { // MHN.init failed ! if (m.getDeclaringClass() == MethodHandle.class && ! isMethodHandleInvokeName(m.getName())) { ! // The JVM did not reify this signature-polymorphic instance. ! // Need a special case here. ! // See comments on MethodHandleNatives.linkMethod. ! MethodType type = MethodType.methodType(m.getReturnType(), m.getParameterTypes()); ! int flags = flagsMods(IS_METHOD, m.getModifiers(), REF_invokeVirtual); ! init(MethodHandle.class, m.getName(), type, flags); ! if (isMethodHandleInvoke()) ! return; ! } ! throw new LinkageError(m.toString()); ! } ! assert(isResolved() && this.clazz != null); ! this.name = m.getName(); ! if (this.type == null) ! this.type = new Object[] { m.getReturnType(), m.getParameterTypes() }; ! if (wantSpecial) { ! if (isAbstract()) ! throw new AbstractMethodError(this.toString()); ! if (getReferenceKind() == REF_invokeVirtual) ! changeReferenceKind(REF_invokeSpecial, REF_invokeVirtual); ! else if (getReferenceKind() == REF_invokeInterface) ! // invokeSpecial on a default method ! changeReferenceKind(REF_invokeSpecial, REF_invokeInterface); ! } ! } public MemberName asSpecial() { switch (getReferenceKind()) { case REF_invokeSpecial: return this; ! case REF_invokeVirtual: return clone().changeReferenceKind(REF_invokeSpecial, REF_invokeVirtual); ! case REF_invokeInterface: return clone().changeReferenceKind(REF_invokeSpecial, REF_invokeInterface); ! case REF_newInvokeSpecial: return clone().changeReferenceKind(REF_invokeSpecial, REF_newInvokeSpecial); } throw new IllegalArgumentException(this.toString()); } /** If this MN is not REF_newInvokeSpecial, return a clone with that ref. kind. * In that case it must already be REF_invokeSpecial. */ public MemberName asConstructor() { switch (getReferenceKind()) { ! case REF_invokeSpecial: return clone().changeReferenceKind(REF_newInvokeSpecial, REF_invokeSpecial); case REF_newInvokeSpecial: return this; } throw new IllegalArgumentException(this.toString()); } /** If this MN is a REF_invokeSpecial, return a clone with the "normal" kind --- 795,822 ---- assert((flags & RECOGNIZED_MODIFIERS) == 0); assert((mods & ~RECOGNIZED_MODIFIERS) == 0); assert((refKind & ~MN_REFERENCE_KIND_MASK) == 0); return flags | mods | (refKind << MN_REFERENCE_KIND_SHIFT); } ! ! ! public MemberName asSpecial() { switch (getReferenceKind()) { case REF_invokeSpecial: return this; ! case REF_invokeVirtual: return cloneAndChangeReferenceKindAndIntern(REF_invokeSpecial, REF_invokeVirtual); ! case REF_invokeInterface: return cloneAndChangeReferenceKindAndIntern(REF_invokeSpecial, REF_invokeInterface); ! case REF_newInvokeSpecial: return cloneAndChangeReferenceKindAndIntern(REF_invokeSpecial, REF_newInvokeSpecial); } throw new IllegalArgumentException(this.toString()); } /** If this MN is not REF_newInvokeSpecial, return a clone with that ref. kind. * In that case it must already be REF_invokeSpecial. */ public MemberName asConstructor() { switch (getReferenceKind()) { ! case REF_invokeSpecial: return cloneAndChangeReferenceKindAndIntern(REF_newInvokeSpecial, REF_invokeSpecial); case REF_newInvokeSpecial: return this; } throw new IllegalArgumentException(this.toString()); } /** If this MN is a REF_invokeSpecial, return a clone with the "normal" kind
*** 591,635 **** newRefKind = normalVirtual; break; } if (newRefKind == refKind) return this; ! result = clone().changeReferenceKind(newRefKind, refKind); assert(this.referenceKindIsConsistentWith(result.getReferenceKind())); return result; } ! /** Create a name for the given reflected constructor. The resulting name will be in a resolved state. */ ! @SuppressWarnings("LeakingThisInConstructor") ! public MemberName(Constructor<?> ctor) { ! ctor.getClass(); // NPE check ! // fill in vmtarget, vmindex while we have ctor in hand: ! MethodHandleNatives.init(this, ctor); ! assert(isResolved() && this.clazz != null); ! this.name = CONSTRUCTOR_NAME; ! if (this.type == null) ! this.type = new Object[] { void.class, ctor.getParameterTypes() }; ! } ! /** Create a name for the given reflected field. The resulting name will be in a resolved state. ! */ ! public MemberName(Field fld) { ! this(fld, false); ! } ! @SuppressWarnings("LeakingThisInConstructor") ! public MemberName(Field fld, boolean makeSetter) { ! fld.getClass(); // NPE check ! // fill in vmtarget, vmindex while we have fld in hand: ! MethodHandleNatives.init(this, fld); ! assert(isResolved() && this.clazz != null); ! this.name = fld.getName(); ! this.type = fld.getType(); ! assert((REF_putStatic - REF_getStatic) == (REF_putField - REF_getField)); ! byte refKind = this.getReferenceKind(); ! assert(refKind == (isStatic() ? REF_getStatic : REF_getField)); ! if (makeSetter) { ! changeReferenceKind((byte)(refKind + (REF_putStatic - REF_getStatic)), refKind); } } public boolean isGetter() { return MethodHandleNatives.refKindIsGetter(getReferenceKind()); } public boolean isSetter() { return MethodHandleNatives.refKindIsSetter(getReferenceKind()); --- 839,862 ---- newRefKind = normalVirtual; break; } if (newRefKind == refKind) return this; ! result = cloneAndChangeReferenceKindAndIntern(newRefKind, refKind); assert(this.referenceKindIsConsistentWith(result.getReferenceKind())); return result; } ! ! private MemberName cloneAndChangeReferenceKindAndIntern(byte refKind, byte oldKind) { ! MemberName tmp0 = null; ! while (tmp0 == null) { ! int tx_token = internTxnToken(); ! tmp0 = clone().changeReferenceKind(refKind, oldKind).intern(this, tx_token); } + return tmp0; } + public boolean isGetter() { return MethodHandleNatives.refKindIsGetter(getReferenceKind()); } public boolean isSetter() { return MethodHandleNatives.refKindIsSetter(getReferenceKind());
*** 637,655 **** public MemberName asSetter() { byte refKind = getReferenceKind(); assert(MethodHandleNatives.refKindIsGetter(refKind)); assert((REF_putStatic - REF_getStatic) == (REF_putField - REF_getField)); byte setterRefKind = (byte)(refKind + (REF_putField - REF_getField)); ! return clone().changeReferenceKind(setterRefKind, refKind); } - /** Create a name for the given class. The resulting name will be in a resolved state. */ - public MemberName(Class<?> type) { - init(type.getDeclaringClass(), type.getSimpleName(), type, - flagsMods(IS_TYPE, type.getModifiers(), REF_NONE)); - initResolved(true); - } - /** * Create a name for a signature-polymorphic invoker. * This is a placeholder for a signature-polymorphic instance * (of MH.invokeExact, etc.) that the JVM does not reify. * See comments on {@link MethodHandleNatives#linkMethod}. --- 864,875 ---- public MemberName asSetter() { byte refKind = getReferenceKind(); assert(MethodHandleNatives.refKindIsGetter(refKind)); assert((REF_putStatic - REF_getStatic) == (REF_putField - REF_getField)); byte setterRefKind = (byte)(refKind + (REF_putField - REF_getField)); ! return cloneAndChangeReferenceKindAndIntern(setterRefKind, refKind); } /** * Create a name for a signature-polymorphic invoker. * This is a placeholder for a signature-polymorphic instance * (of MH.invokeExact, etc.) that the JVM does not reify. * See comments on {@link MethodHandleNatives#linkMethod}.
*** 662,674 **** mem.flags |= mods; // it's not resolved, but add these modifiers anyway assert(mem.isMethodHandleInvoke()) : mem; return mem; } - // bare-bones constructor; the JVM will fill it in - MemberName() { } - // locally useful cloner @Override protected MemberName clone() { try { return (MemberName) super.clone(); } catch (CloneNotSupportedException ex) { --- 882,891 ----
*** 713,768 **** && this.getReferenceKind() == that.getReferenceKind() && Objects.equals(this.name, that.name) && Objects.equals(this.getType(), that.getType()); } ! // Construction from symbolic parts, for queries: ! /** Create a field or type name from the given components: ! * Declaring class, name, type, reference kind. ! * The declaring class may be supplied as null if this is to be a bare name and type. ! * The resulting name will in an unresolved state. */ ! public MemberName(Class<?> defClass, String name, Class<?> type, byte refKind) { ! init(defClass, name, type, flagsMods(IS_FIELD, 0, refKind)); ! initResolved(false); } ! /** Create a method or constructor name from the given components: ! * Declaring class, name, type, reference kind. ! * It will be a constructor if and only if the name is {@code "&lt;init&gt;"}. ! * The declaring class may be supplied as null if this is to be a bare name and type. ! * The last argument is optional, a boolean which requests REF_invokeSpecial. ! * The resulting name will in an unresolved state. ! */ ! public MemberName(Class<?> defClass, String name, MethodType type, byte refKind) { ! int initFlags = (name != null && name.equals(CONSTRUCTOR_NAME) ? IS_CONSTRUCTOR : IS_METHOD); ! init(defClass, name, type, flagsMods(initFlags, 0, refKind)); ! initResolved(false); } ! /** Create a method, constructor, or field name from the given components: ! * Reference kind, declaring class, name, type. ! */ ! public MemberName(byte refKind, Class<?> defClass, String name, Object type) { ! int kindFlags; ! if (MethodHandleNatives.refKindIsField(refKind)) { ! kindFlags = IS_FIELD; ! if (!(type instanceof Class)) ! throw newIllegalArgumentException("not a field type"); ! } else if (MethodHandleNatives.refKindIsMethod(refKind)) { ! kindFlags = IS_METHOD; ! if (!(type instanceof MethodType)) ! throw newIllegalArgumentException("not a method type"); ! } else if (refKind == REF_newInvokeSpecial) { ! kindFlags = IS_CONSTRUCTOR; ! if (!(type instanceof MethodType) || ! !CONSTRUCTOR_NAME.equals(name)) ! throw newIllegalArgumentException("not a constructor type or name"); ! } else { ! throw newIllegalArgumentException("bad reference kind "+refKind); } ! init(defClass, name, type, flagsMods(kindFlags, 0, refKind)); ! initResolved(false); } /** Query whether this member name is resolved to a non-static, non-final method. */ public boolean hasReceiverTypeDispatch() { return MethodHandleNatives.refKindDoesDispatch(getReferenceKind()); } --- 930,1000 ---- && this.getReferenceKind() == that.getReferenceKind() && Objects.equals(this.name, that.name) && Objects.equals(this.getType(), that.getType()); } ! @Override ! public int compareTo(Object o) { ! MemberName that = (MemberName) o; ! ! /* First test equals. This make the ordering checks easier because we ! * don't have to be precise and can use hash codes. */ ! if (equals(that)) { ! return 0; } ! ! int diff = Integer.compare(this.name.hashCode(), that.name.hashCode()); ! if (diff != 0) { ! return diff; } ! ! diff = this.getReferenceKind() - that.getReferenceKind(); ! if (diff != 0) { ! return diff; } ! ! diff = Integer.compare(this.getType().hashCode(), that.getType().hashCode()); ! if (diff != 0) { ! return diff; ! } ! ! // Hashcodes apparently collided, try more detail. ! diff = this.name.compareTo(that.name); ! if (diff != 0) { ! return diff; ! } ! ! // The classes ought to all be equal anyway in the usual use of ! // compareTo, so check these later, ! // but before comparing getType.toString(). ! diff = Integer.compare(this.clazz.hashCode(),that.clazz.hashCode()); ! if (diff != 0) { ! return diff; ! } ! ! diff = this.getType().toString().compareTo(that.getType().toString()); ! if (diff != 0) { ! return diff; ! } ! ! diff = this.clazz.getName().compareTo(that.clazz.getName()); ! if (diff != 0) { ! return diff; ! } ! ! ClassLoader thisCl = this.clazz.getClassLoader(); ! ClassLoader thatCl = that.clazz.getClassLoader(); ! ! if (thisCl == thatCl) return 0; ! ! diff = Integer.compare(thisCl == null ? 0 : thisCl.hashCode(), ! thatCl == null ? 0 : thatCl.hashCode()); ! ! return diff; } + /** Query whether this member name is resolved to a non-static, non-final method. */ public boolean hasReceiverTypeDispatch() { return MethodHandleNatives.refKindDoesDispatch(getReferenceKind()); }
*** 774,790 **** */ public boolean isResolved() { return resolution == null; } - private void initResolved(boolean isResolved) { - assert(this.resolution == null); // not initialized yet! - if (!isResolved) - this.resolution = this; - assert(isResolved() == isResolved); - } - void checkForTypeAlias() { if (isInvocable()) { MethodType type; if (this.type instanceof MethodType) type = (MethodType) this.type; --- 1006,1015 ----
*** 887,897 **** */ /*non-public*/ static class Factory { private Factory() { } // singleton pattern static Factory INSTANCE = new Factory(); ! private static int ALLOWED_FLAGS = ALL_KINDS; /// Queries List<MemberName> getMembers(Class<?> defc, String matchName, Object matchType, int matchFlags, Class<?> lookupClass) { --- 1112,1122 ---- */ /*non-public*/ static class Factory { private Factory() { } // singleton pattern static Factory INSTANCE = new Factory(); ! private final static int ALLOWED_FLAGS = ALL_KINDS; /// Queries List<MemberName> getMembers(Class<?> defc, String matchName, Object matchType, int matchFlags, Class<?> lookupClass) {
*** 953,963 **** * Super types are searched (for inherited members) if {@code searchSupers} is true. * Access checking is performed on behalf of the given {@code lookupClass}. * If lookup fails or access is not permitted, null is returned. * Otherwise a fresh copy of the given member is returned, with modifier bits filled in. */ ! private MemberName resolve(byte refKind, MemberName ref, Class<?> lookupClass) { MemberName m = ref.clone(); // JVM will side-effect the ref assert(refKind == m.getReferenceKind()); try { m = MethodHandleNatives.resolve(m, lookupClass); m.checkForTypeAlias(); --- 1178,1188 ---- * Super types are searched (for inherited members) if {@code searchSupers} is true. * Access checking is performed on behalf of the given {@code lookupClass}. * If lookup fails or access is not permitted, null is returned. * Otherwise a fresh copy of the given member is returned, with modifier bits filled in. */ ! private static MemberName resolve(byte refKind, MemberName ref, Class<?> lookupClass) { MemberName m = ref.clone(); // JVM will side-effect the ref assert(refKind == m.getReferenceKind()); try { m = MethodHandleNatives.resolve(m, lookupClass); m.checkForTypeAlias();
*** 969,978 **** --- 1194,1204 ---- return m; } assert(m.referenceKindIsConsistent()); m.initResolved(true); assert(m.vminfoIsConsistent()); + // m = m.intern(); // do not intern -- caller should intern instead. return m; } /** Produce a resolved version of the given member. * Super types are searched (for inherited members) if {@code searchSupers} is true. * Access checking is performed on behalf of the given {@code lookupClass}.
*** 982,1011 **** public <NoSuchMemberException extends ReflectiveOperationException> MemberName resolveOrFail(byte refKind, MemberName m, Class<?> lookupClass, Class<NoSuchMemberException> nsmClass) throws IllegalAccessException, NoSuchMemberException { ! MemberName result = resolve(refKind, m, lookupClass); ! if (result.isResolved()) return result; ReflectiveOperationException ex = result.makeAccessException(); ! if (ex instanceof IllegalAccessException) throw (IllegalAccessException) ex; throw nsmClass.cast(ex); } /** Produce a resolved version of the given member. * Super types are searched (for inherited members) if {@code searchSupers} is true. * Access checking is performed on behalf of the given {@code lookupClass}. * If lookup fails or access is not permitted, return null. * Otherwise a fresh copy of the given member is returned, with modifier bits filled in. */ public MemberName resolveOrNull(byte refKind, MemberName m, Class<?> lookupClass) { ! MemberName result = resolve(refKind, m, lookupClass); ! if (result.isResolved()) return result; - return null; } /** Return a list of all methods defined by the given class. * Super types are searched (for inherited members) if {@code searchSupers} is true. * Access checking is performed on behalf of the given {@code lookupClass}. * Inaccessible members are not added to the last. */ --- 1208,1273 ---- public <NoSuchMemberException extends ReflectiveOperationException> MemberName resolveOrFail(byte refKind, MemberName m, Class<?> lookupClass, Class<NoSuchMemberException> nsmClass) throws IllegalAccessException, NoSuchMemberException { ! MemberName result = resolveOrNot(refKind, m, lookupClass); ! ! if (result.isResolved()) { return result; + } else { // not resolved, throw exception ReflectiveOperationException ex = result.makeAccessException(); ! if (ex instanceof IllegalAccessException) { ! throw (IllegalAccessException) ex; ! } throw nsmClass.cast(ex); } + } /** Produce a resolved version of the given member. * Super types are searched (for inherited members) if {@code searchSupers} is true. * Access checking is performed on behalf of the given {@code lookupClass}. * If lookup fails or access is not permitted, return null. * Otherwise a fresh copy of the given member is returned, with modifier bits filled in. */ public MemberName resolveOrNull(byte refKind, MemberName m, Class<?> lookupClass) { ! MemberName result = resolveOrNot(refKind, m, lookupClass); ! return result.isResolved() ? result : null; ! } ! ! private static ! MemberName resolveOrNot(byte refKind, MemberName m, Class<?> lookupClass) { ! MemberName result = null; ! Class tx_class = m.getClass(); ! while (result == null) { // iterate till no race. ! int txn_token = internTxnToken(tx_class); ! ! MemberName result0 = resolve(refKind, m, lookupClass); ! ! if (result0.isResolved()) { ! if (result0.getClass() != tx_class) { ! Class prev_tx_class = tx_class; ! int prev_txn_token = txn_token; ! tx_class = result0.getClass(); ! txn_token = internTxnToken(tx_class); ! // Zero is a special case. ! if (txn_token != 0 || ! prev_txn_token != internTxnToken(prev_tx_class)) { ! // Resolved class is different and at least one ! // redef of it occurred, therefore repeat with ! // proper class for race consistency checking. ! continue; ! } ! } ! result = result0.intern(txn_token); ! } else { ! return result0; ! } ! } return result; } + /** Return a list of all methods defined by the given class. * Super types are searched (for inherited members) if {@code searchSupers} is true. * Access checking is performed on behalf of the given {@code lookupClass}. * Inaccessible members are not added to the last. */
*** 1067,1077 **** for (int i = 0; i < length; i++) buf[i] = new MemberName(); return buf; } } - - // static { - // System.out.println("Hello world! My methods are:"); - // System.out.println(Factory.INSTANCE.getMethods(MemberName.class, true, null)); - // } } --- 1329,1334 ----
src/java.base/share/classes/java/lang/invoke/MemberName.java
Index Unified diffs Context diffs Sdiffs Patch New Old Previous File Next File