src/java.base/share/classes/java/lang/invoke/MemberName.java
Index
Unified diffs
Context diffs
Sdiffs
Patch
New
Old
Previous File
Next File
*** old/src/java.base/share/classes/java/lang/invoke/MemberName.java Fri Oct 17 13:54:29 2014
--- new/src/java.base/share/classes/java/lang/invoke/MemberName.java Fri Oct 17 13:54:29 2014
*** 1,7 ****
--- 1,7 ----
/*
! * Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved.
! * 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,49 ----
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 java.util.Objects;
/**
* A {@code MemberName} is a compact symbolic datum which fully characterizes
* a method or field reference.
*** 67,85 ****
--- 69,286 ----
* 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 {
+ @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
+ // 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) {
+ MemberName tmp = new MemberName(m, wantSpecial);
+ // Unreflected member names are resolved so intern them here.
+ return tmp.intern();
+ }
+
+ /**
+ * 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() };
+ }
+ }
+
+ static public MemberName make(Constructor<?> ctor) {
+ MemberName tmp = new MemberName(ctor);
+ // Unreflected member names are resolved so intern them here.
+ return tmp.intern();
+ }
+
+
+ /** 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);
+ }
+ }
+
+ static public MemberName make(Field field, boolean makeSetter) {
+ MemberName tmp = new MemberName(field, makeSetter);
+ // Unreflected member names are resolved so intern them here.
+ return tmp.intern();
+ }
+
+ /** 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() {
+ return clazz.internMemberName(this);
+ }
+
/** 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;
*** 477,501 ****
--- 678,687 ----
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() {
*** 513,559 ****
--- 699,708 ----
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);
*** 595,635 ****
--- 744,753 ----
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());
*** 639,655 ****
--- 757,766 ----
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}.
*** 662,674 ****
--- 773,782 ----
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) {
*** 713,767 ****
--- 821,863 ----
&& 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.
+ @Override
+ public int compareTo(Object o) {
+ MemberName that = (MemberName) o;
+
+ /* First try an equals. This make the ordering checks easier because we
+ * don't have to be precise and can use hash codes.
*/
! public MemberName(Class<?> defClass, String name, Class<?> type, byte refKind) {
! init(defClass, name, type, flagsMods(IS_FIELD, 0, refKind));
initResolved(false);
! if (equals(that)) {
! return 0;
}
/** 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);
+
+ final int clazzDiff = this.clazz.hashCode() - that.clazz.hashCode();
+ if (clazzDiff != 0) {
+ return clazzDiff;
}
/** 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);
+
+ final int kindDiff = this.getReferenceKind() - that.getReferenceKind();
+ if (kindDiff != 0) {
+ return kindDiff;
}
init(defClass, name, type, flagsMods(kindFlags, 0, refKind));
! initResolved(false);
+
! final int nameDiff = this.name.hashCode() - that.name.hashCode();
+ if (nameDiff != 0) {
+ return nameDiff;
+ }
+
+ final int typeDiff = this.getType().hashCode() - that.getType().hashCode();
+ if (typeDiff != 0) {
+ return typeDiff;
+ }
+
+ // In the unlikely case all values above are equal we just return 1.
+ return 1;
}
/** Query whether this member name is resolved to a non-static, non-final method.
*/
public boolean hasReceiverTypeDispatch() {
return MethodHandleNatives.refKindDoesDispatch(getReferenceKind());
*** 774,790 ****
--- 870,879 ----
*/
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;
*** 960,969 ****
--- 1049,1059 ----
assert(refKind == m.getReferenceKind());
try {
m = MethodHandleNatives.resolve(m, lookupClass);
m.checkForTypeAlias();
m.resolution = null;
+ m.intern();
} catch (LinkageError ex) {
// JVM reports that the "bytecode behavior" would get an error
assert(!m.isResolved());
m.resolution = ex;
return m;
*** 1067,1077 ****
--- 1157,1162 ----
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));
// }
}
src/java.base/share/classes/java/lang/invoke/MemberName.java
Index
Unified diffs
Context diffs
Sdiffs
Patch
New
Old
Previous File
Next File