提交 988d2756 编写于 作者: J jrose

7044892: JSR 292: API entry points sometimes throw the wrong exceptions or...

7044892: JSR 292: API entry points sometimes throw the wrong exceptions or doesn't throw the expected one
Summary: point-fixes for 7038847, 7038860, 7042656, 7042829, 7041853, and several other reports
Reviewed-by: never, kvn
上级 0249ef03
...@@ -546,6 +546,10 @@ class AdapterMethodHandle extends BoundMethodHandle { ...@@ -546,6 +546,10 @@ class AdapterMethodHandle extends BoundMethodHandle {
} }
static MethodHandle makeVarargsCollector(MethodHandle target, Class<?> arrayType) { static MethodHandle makeVarargsCollector(MethodHandle target, Class<?> arrayType) {
MethodType type = target.type();
int last = type.parameterCount() - 1;
if (type.parameterType(last) != arrayType)
target = target.asType(type.changeParameterType(last, arrayType));
return new AsVarargsCollector(target, arrayType); return new AsVarargsCollector(target, arrayType);
} }
...@@ -1144,7 +1148,7 @@ class AdapterMethodHandle extends BoundMethodHandle { ...@@ -1144,7 +1148,7 @@ class AdapterMethodHandle extends BoundMethodHandle {
} }
@Override @Override
public String toString() { String debugString() {
return getNameString(nonAdapter((MethodHandle)vmtarget), this); return getNameString(nonAdapter((MethodHandle)vmtarget), this);
} }
......
...@@ -155,7 +155,7 @@ class BoundMethodHandle extends MethodHandle { ...@@ -155,7 +155,7 @@ class BoundMethodHandle extends MethodHandle {
} }
@Override @Override
public String toString() { String debugString() {
return addTypeString(baseName(), this); return addTypeString(baseName(), this);
} }
......
...@@ -234,7 +234,7 @@ class FilterGeneric { ...@@ -234,7 +234,7 @@ class FilterGeneric {
protected final MethodHandle target; // ultimate target protected final MethodHandle target; // ultimate target
@Override @Override
public String toString() { String debugString() {
return addTypeString(target, this); return addTypeString(target, this);
} }
......
...@@ -41,7 +41,7 @@ class FilterOneArgument extends BoundMethodHandle { ...@@ -41,7 +41,7 @@ class FilterOneArgument extends BoundMethodHandle {
protected final MethodHandle target; // Object -> Object protected final MethodHandle target; // Object -> Object
@Override @Override
public String toString() { String debugString() {
return target.toString(); return target.toString();
} }
......
...@@ -260,7 +260,7 @@ class FromGeneric { ...@@ -260,7 +260,7 @@ class FromGeneric {
protected final MethodHandle target; // (any**N) => R protected final MethodHandle target; // (any**N) => R
@Override @Override
public String toString() { String debugString() {
return addTypeString(target, this); return addTypeString(target, this);
} }
......
...@@ -26,6 +26,7 @@ ...@@ -26,6 +26,7 @@
package java.lang.invoke; package java.lang.invoke;
import java.util.ArrayList;
import sun.invoke.util.ValueConversions; import sun.invoke.util.ValueConversions;
import static java.lang.invoke.MethodHandleStatics.*; import static java.lang.invoke.MethodHandleStatics.*;
...@@ -750,11 +751,46 @@ public abstract class MethodHandle { ...@@ -750,11 +751,46 @@ public abstract class MethodHandle {
* @see #asCollector * @see #asCollector
*/ */
public MethodHandle asSpreader(Class<?> arrayType, int arrayLength) { public MethodHandle asSpreader(Class<?> arrayType, int arrayLength) {
Class<?> arrayElement = arrayType.getComponentType(); asSpreaderChecks(arrayType, arrayLength);
if (arrayElement == null) throw newIllegalArgumentException("not an array type"); return MethodHandleImpl.spreadArguments(this, arrayType, arrayLength);
}
private void asSpreaderChecks(Class<?> arrayType, int arrayLength) {
spreadArrayChecks(arrayType, arrayLength);
int nargs = type().parameterCount(); int nargs = type().parameterCount();
if (nargs < arrayLength) throw newIllegalArgumentException("bad spread array length"); if (nargs < arrayLength) throw newIllegalArgumentException("bad spread array length");
return MethodHandleImpl.spreadArguments(this, arrayType, arrayLength); if (arrayType != Object[].class && arrayLength != 0) {
boolean sawProblem = false;
Class<?> arrayElement = arrayType.getComponentType();
for (int i = nargs - arrayLength; i < nargs; i++) {
if (!MethodType.canConvert(arrayElement, type().parameterType(i))) {
sawProblem = true;
break;
}
}
if (sawProblem) {
ArrayList<Class<?>> ptypes = new ArrayList<Class<?>>(type().parameterList());
for (int i = nargs - arrayLength; i < nargs; i++) {
ptypes.set(i, arrayElement);
}
// elicit an error:
this.asType(MethodType.methodType(type().returnType(), ptypes));
}
}
}
private void spreadArrayChecks(Class<?> arrayType, int arrayLength) {
Class<?> arrayElement = arrayType.getComponentType();
if (arrayElement == null)
throw newIllegalArgumentException("not an array type", arrayType);
if ((arrayLength & 0x7F) != arrayLength) {
if ((arrayLength & 0xFF) != arrayLength)
throw newIllegalArgumentException("array length is not legal", arrayLength);
assert(arrayLength >= 128);
if (arrayElement == long.class ||
arrayElement == double.class)
throw newIllegalArgumentException("array length is not legal for long[] or double[]", arrayLength);
}
} }
/** /**
...@@ -802,10 +838,8 @@ public abstract class MethodHandle { ...@@ -802,10 +838,8 @@ public abstract class MethodHandle {
return MethodHandleImpl.collectArguments(this, type.parameterCount()-1, collector); return MethodHandleImpl.collectArguments(this, type.parameterCount()-1, collector);
} }
private void asCollectorChecks(Class<?> arrayType, int arrayLength) { private void asCollectorChecks(Class<?> arrayType, int arrayLength) {
Class<?> arrayElement = arrayType.getComponentType(); spreadArrayChecks(arrayType, arrayLength);
if (arrayElement == null)
throw newIllegalArgumentException("not an array type", arrayType);
int nargs = type().parameterCount(); int nargs = type().parameterCount();
if (nargs == 0 || !type().parameterType(nargs-1).isAssignableFrom(arrayType)) if (nargs == 0 || !type().parameterType(nargs-1).isAssignableFrom(arrayType))
throw newIllegalArgumentException("array type not assignable to trailing argument", this, arrayType); throw newIllegalArgumentException("array type not assignable to trailing argument", this, arrayType);
...@@ -965,8 +999,8 @@ assert(failed); ...@@ -965,8 +999,8 @@ assert(failed);
*/ */
public MethodHandle asVarargsCollector(Class<?> arrayType) { public MethodHandle asVarargsCollector(Class<?> arrayType) {
Class<?> arrayElement = arrayType.getComponentType(); Class<?> arrayElement = arrayType.getComponentType();
if (arrayElement == null) throw newIllegalArgumentException("not an array type"); asCollectorChecks(arrayType, 0);
return MethodHandles.asVarargsCollector(this, arrayType); return AdapterMethodHandle.makeVarargsCollector(this, arrayType);
} }
/** /**
...@@ -1043,6 +1077,12 @@ assert(failed); ...@@ -1043,6 +1077,12 @@ assert(failed);
*/ */
@Override @Override
public String toString() { public String toString() {
if (DEBUG_METHOD_HANDLE_NAMES) return debugString();
return "MethodHandle"+type;
}
/*non-public*/
String debugString() {
return getNameString(this); return getNameString(this);
} }
} }
...@@ -163,7 +163,7 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP; ...@@ -163,7 +163,7 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
} }
} }
@Override @Override
public String toString() { String debugString() {
return addTypeString(allocateClass.getSimpleName(), this); return addTypeString(allocateClass.getSimpleName(), this);
} }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
...@@ -307,7 +307,7 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP; ...@@ -307,7 +307,7 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
this.base = staticBase(field); this.base = staticBase(field);
} }
@Override @Override
public String toString() { return addTypeString(name, this); } String debugString() { return addTypeString(name, this); }
int getFieldI(C obj) { return unsafe.getInt(obj, offset); } int getFieldI(C obj) { return unsafe.getInt(obj, offset); }
void setFieldI(C obj, int x) { unsafe.putInt(obj, offset, x); } void setFieldI(C obj, int x) { unsafe.putInt(obj, offset, x); }
...@@ -338,8 +338,9 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP; ...@@ -338,8 +338,9 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
try { try {
// FIXME: Should not have to create 'f' to get this value. // FIXME: Should not have to create 'f' to get this value.
f = c.getDeclaredField(field.getName()); f = c.getDeclaredField(field.getName());
// Note: Previous line might invalidly throw SecurityException (7042829)
return unsafe.staticFieldBase(f); return unsafe.staticFieldBase(f);
} catch (Exception ee) { } catch (NoSuchFieldException ee) {
throw uncaughtException(ee); throw uncaughtException(ee);
} }
} }
...@@ -936,7 +937,7 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP; ...@@ -936,7 +937,7 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
} }
} }
@Override @Override
public String toString() { String debugString() {
return addTypeString(target, this); return addTypeString(target, this);
} }
private Object invoke_V(Object... av) throws Throwable { private Object invoke_V(Object... av) throws Throwable {
...@@ -1081,7 +1082,7 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP; ...@@ -1081,7 +1082,7 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
this.catcher = catcher; this.catcher = catcher;
} }
@Override @Override
public String toString() { String debugString() {
return addTypeString(target, this); return addTypeString(target, this);
} }
private Object invoke_V(Object... av) throws Throwable { private Object invoke_V(Object... av) throws Throwable {
...@@ -1248,8 +1249,4 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP; ...@@ -1248,8 +1249,4 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
static MethodHandle getBootstrap(Class<?> callerClass) { static MethodHandle getBootstrap(Class<?> callerClass) {
return MethodHandleNatives.getBootstrap(callerClass); return MethodHandleNatives.getBootstrap(callerClass);
} }
static MethodHandle asVarargsCollector(MethodHandle target, Class<?> arrayType) {
return AdapterMethodHandle.makeVarargsCollector(target, arrayType);
}
} }
...@@ -35,6 +35,8 @@ package java.lang.invoke; ...@@ -35,6 +35,8 @@ package java.lang.invoke;
private MethodHandleStatics() { } // do not instantiate private MethodHandleStatics() { } // do not instantiate
static final boolean DEBUG_METHOD_HANDLE_NAMES = Boolean.getBoolean("java.lang.invoke.MethodHandle.DEBUG_NAMES");
/*non-public*/ static String getNameString(MethodHandle target, MethodType type) { /*non-public*/ static String getNameString(MethodHandle target, MethodType type) {
if (type == null) if (type == null)
type = target.type(); type = target.type();
......
...@@ -1065,6 +1065,7 @@ return mh1; ...@@ -1065,6 +1065,7 @@ return mh1;
if (!method.isProtected() || method.isStatic() if (!method.isProtected() || method.isStatic()
|| allowedModes == TRUSTED || allowedModes == TRUSTED
|| method.getDeclaringClass() == lookupClass() || method.getDeclaringClass() == lookupClass()
|| VerifyAccess.isSamePackage(method.getDeclaringClass(), lookupClass())
|| (ALLOW_NESTMATE_ACCESS && || (ALLOW_NESTMATE_ACCESS &&
VerifyAccess.isSamePackageMember(method.getDeclaringClass(), lookupClass()))) VerifyAccess.isSamePackageMember(method.getDeclaringClass(), lookupClass())))
return mh; return mh;
...@@ -2383,9 +2384,4 @@ System.out.println((int) f0.invokeExact("x", "y")); // 2 ...@@ -2383,9 +2384,4 @@ System.out.println((int) f0.invokeExact("x", "y")); // 2
} }
return null; return null;
} }
/*non-public*/
static MethodHandle asVarargsCollector(MethodHandle target, Class<?> arrayType) {
return MethodHandleImpl.asVarargsCollector(target, arrayType);
}
} }
...@@ -163,7 +163,13 @@ class MethodType implements java.io.Serializable { ...@@ -163,7 +163,13 @@ class MethodType implements java.io.Serializable {
public static public static
MethodType methodType(Class<?> rtype, List<Class<?>> ptypes) { MethodType methodType(Class<?> rtype, List<Class<?>> ptypes) {
boolean notrust = false; // random List impl. could return evil ptypes array boolean notrust = false; // random List impl. could return evil ptypes array
return makeImpl(rtype, ptypes.toArray(NO_PTYPES), notrust); return makeImpl(rtype, listToArray(ptypes), notrust);
}
private static Class<?>[] listToArray(List<Class<?>> ptypes) {
// sanity check the size before the toArray call, since size might be huge
checkSlotCount(ptypes.size());
return ptypes.toArray(NO_PTYPES);
} }
/** /**
...@@ -228,7 +234,7 @@ class MethodType implements java.io.Serializable { ...@@ -228,7 +234,7 @@ class MethodType implements java.io.Serializable {
*/ */
/*trusted*/ static /*trusted*/ static
MethodType makeImpl(Class<?> rtype, Class<?>[] ptypes, boolean trusted) { MethodType makeImpl(Class<?> rtype, Class<?>[] ptypes, boolean trusted) {
if (ptypes == null || ptypes.length == 0) { if (ptypes.length == 0) {
ptypes = NO_PTYPES; trusted = true; ptypes = NO_PTYPES; trusted = true;
} }
MethodType mt1 = new MethodType(rtype, ptypes); MethodType mt1 = new MethodType(rtype, ptypes);
...@@ -372,7 +378,7 @@ class MethodType implements java.io.Serializable { ...@@ -372,7 +378,7 @@ class MethodType implements java.io.Serializable {
* @throws NullPointerException if {@code ptypesToInsert} or any of its elements is null * @throws NullPointerException if {@code ptypesToInsert} or any of its elements is null
*/ */
public MethodType insertParameterTypes(int num, List<Class<?>> ptypesToInsert) { public MethodType insertParameterTypes(int num, List<Class<?>> ptypesToInsert) {
return insertParameterTypes(num, ptypesToInsert.toArray(NO_PTYPES)); return insertParameterTypes(num, listToArray(ptypesToInsert));
} }
/** /**
...@@ -641,7 +647,8 @@ class MethodType implements java.io.Serializable { ...@@ -641,7 +647,8 @@ class MethodType implements java.io.Serializable {
} }
return true; return true;
} }
private static boolean canConvert(Class<?> src, Class<?> dst) { /*non-public*/
static boolean canConvert(Class<?> src, Class<?> dst) {
if (src == dst || dst == void.class) return true; if (src == dst || dst == void.class) return true;
if (src.isPrimitive() && dst.isPrimitive()) { if (src.isPrimitive() && dst.isPrimitive()) {
if (!Wrapper.forPrimitiveType(dst) if (!Wrapper.forPrimitiveType(dst)
...@@ -739,9 +746,14 @@ class MethodType implements java.io.Serializable { ...@@ -739,9 +746,14 @@ class MethodType implements java.io.Serializable {
public static MethodType fromMethodDescriptorString(String descriptor, ClassLoader loader) public static MethodType fromMethodDescriptorString(String descriptor, ClassLoader loader)
throws IllegalArgumentException, TypeNotPresentException throws IllegalArgumentException, TypeNotPresentException
{ {
if (!descriptor.startsWith("(") || // also generates NPE if needed
descriptor.indexOf(')') < 0 ||
descriptor.indexOf('.') >= 0)
throw new IllegalArgumentException("not a method descriptor: "+descriptor);
List<Class<?>> types = BytecodeDescriptor.parseMethod(descriptor, loader); List<Class<?>> types = BytecodeDescriptor.parseMethod(descriptor, loader);
Class<?> rtype = types.remove(types.size() - 1); Class<?> rtype = types.remove(types.size() - 1);
Class<?>[] ptypes = types.toArray(NO_PTYPES); checkSlotCount(types.size());
Class<?>[] ptypes = listToArray(types);
return makeImpl(rtype, ptypes, true); return makeImpl(rtype, ptypes, true);
} }
......
...@@ -448,6 +448,8 @@ class MethodTypeForm { ...@@ -448,6 +448,8 @@ class MethodTypeForm {
Class<?>[] cs = null; Class<?>[] cs = null;
for (int imax = ts.length, i = 0; i < imax; i++) { for (int imax = ts.length, i = 0; i < imax; i++) {
Class<?> c = canonicalize(ts[i], how); Class<?> c = canonicalize(ts[i], how);
if (c == void.class)
c = null; // a Void parameter was unwrapped to void; ignore
if (c != null) { if (c != null) {
if (cs == null) if (cs == null)
cs = ts.clone(); cs = ts.clone();
......
...@@ -126,7 +126,7 @@ class SpreadGeneric { ...@@ -126,7 +126,7 @@ class SpreadGeneric {
return spreadGen; return spreadGen;
} }
public String toString() { String debugString() {
return getClass().getSimpleName()+targetType+"["+spreadCount+"]"; return getClass().getSimpleName()+targetType+"["+spreadCount+"]";
} }
...@@ -224,7 +224,7 @@ class SpreadGeneric { ...@@ -224,7 +224,7 @@ class SpreadGeneric {
protected final MethodHandle target; // (any**N) => R protected final MethodHandle target; // (any**N) => R
@Override @Override
public String toString() { String debugString() {
return addTypeString(target, this); return addTypeString(target, this);
} }
......
...@@ -258,7 +258,7 @@ class ToGeneric { ...@@ -258,7 +258,7 @@ class ToGeneric {
return toGen; return toGen;
} }
public String toString() { String debugString() {
return "ToGeneric"+entryType return "ToGeneric"+entryType
+(primsAtEndOrder!=null?"[reorder]":""); +(primsAtEndOrder!=null?"[reorder]":"");
} }
...@@ -340,7 +340,7 @@ class ToGeneric { ...@@ -340,7 +340,7 @@ class ToGeneric {
protected final MethodHandle convert; // Object -> R protected final MethodHandle convert; // Object -> R
@Override @Override
public String toString() { String debugString() {
return target == null ? "prototype:"+convert : addTypeString(target, this); return target == null ? "prototype:"+convert : addTypeString(target, this);
} }
......
...@@ -505,8 +505,15 @@ public class MethodHandlesTest { ...@@ -505,8 +505,15 @@ public class MethodHandlesTest {
System.out.print(':'); System.out.print(':');
} }
static final boolean DEBUG_METHOD_HANDLE_NAMES = Boolean.getBoolean("java.lang.invoke.MethodHandle.DEBUG_NAMES");
// rough check of name string // rough check of name string
static void assertNameStringContains(Object x, String s) { static void assertNameStringContains(MethodHandle x, String s) {
if (!DEBUG_METHOD_HANDLE_NAMES) {
// ignore s
assertEquals("MethodHandle"+x.type(), x.toString());
return;
}
if (x.toString().contains(s)) return; if (x.toString().contains(s)) return;
assertEquals(s, x); assertEquals(s, x);
} }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册