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 "<init>"}.
+ * 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 "<init>"}.
*/
+ @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 "<init>"}.
! * 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