OpenJDK / amber / amber
changeset 8347:e5daa5772ffd
7013730: JSR 292 reflective operations should report errors with standard exception types
Summary: remove NoAccessException, replace it by ReflectiveOperationException subtypes; adjust javadoc of exceptions
Reviewed-by: twisti
line wrap: on
line diff
--- a/jdk/src/share/classes/java/dyn/CallSite.java Fri Feb 11 01:26:28 2011 -0800 +++ b/jdk/src/share/classes/java/dyn/CallSite.java Fri Feb 11 01:26:32 2011 -0800 @@ -228,7 +228,7 @@ try { GET_TARGET = MethodHandles.Lookup.IMPL_LOOKUP. findVirtual(CallSite.class, "getTarget", MethodType.methodType(MethodHandle.class)); - } catch (NoAccessException ignore) { + } catch (ReflectiveOperationException ignore) { throw new InternalError(); } }
--- a/jdk/src/share/classes/java/dyn/Linkage.java Fri Feb 11 01:26:28 2011 -0800 +++ b/jdk/src/share/classes/java/dyn/Linkage.java Fri Feb 11 01:26:32 2011 -0800 @@ -88,7 +88,7 @@ MethodHandle bootstrapMethod; try { bootstrapMethod = lookup.findStatic(runtime, name, BOOTSTRAP_METHOD_TYPE); - } catch (NoAccessException ex) { + } catch (ReflectiveOperationException ex) { throw new IllegalArgumentException("no such bootstrap method in "+runtime+": "+name, ex); } MethodHandleImpl.registerBootstrap(IMPL_TOKEN, callerClass, bootstrapMethod);
--- a/jdk/src/share/classes/java/dyn/MethodHandles.java Fri Feb 11 01:26:28 2011 -0800 +++ b/jdk/src/share/classes/java/dyn/MethodHandles.java Fri Feb 11 01:26:32 2011 -0800 @@ -226,9 +226,14 @@ * the containing class is not accessible to the lookup class, or * because the desired class member is missing, or because the * desired class member is not accessible to the lookup class. - * It can also fail if a security manager is installed and refuses - * access. In any of these cases, an exception will be - * thrown from the attempted lookup. + * In any of these cases, a {@code ReflectiveOperationException} will be + * thrown from the attempted lookup. The exact class will be one of + * the following: + * <ul> + * <li>NoSuchMethodException — if a method is requested but does not exist + * <li>NoSuchFieldException — if a field is requested but does not exist + * <li>IllegalAccessException — if the member exists but an access check fails + * </ul> * <p> * In general, the conditions under which a method handle may be * looked up for a method {@code M} are exactly equivalent to the conditions @@ -511,10 +516,12 @@ * @param name the name of the method * @param type the type of the method * @return the desired method handle - * @exception NoAccessException if the method does not exist or access checking fails + * @throws NoSuchMethodException if the method does not exist + * @throws IllegalAccessException if access checking fails, or if the method is not {@code static} + * @throws NullPointerException if any argument is null */ public - MethodHandle findStatic(Class<?> refc, String name, MethodType type) throws NoAccessException { + MethodHandle findStatic(Class<?> refc, String name, MethodType type) throws NoSuchMethodException, IllegalAccessException { MemberName method = resolveOrFail(refc, name, type, true); checkMethod(refc, method, true); return MethodHandleImpl.findMethod(IMPL_TOKEN, method, false, lookupClassOrNull()); @@ -549,9 +556,11 @@ * @param name the name of the method * @param type the type of the method, with the receiver argument omitted * @return the desired method handle - * @exception NoAccessException if the method does not exist or access checking fails + * @throws NoSuchMethodException if the method does not exist + * @throws IllegalAccessException if access checking fails, or if the method is {@code static} + * @throws NullPointerException if any argument is null */ - public MethodHandle findVirtual(Class<?> refc, String name, MethodType type) throws NoAccessException { + public MethodHandle findVirtual(Class<?> refc, String name, MethodType type) throws NoSuchMethodException, IllegalAccessException { MemberName method = resolveOrFail(refc, name, type, false); checkMethod(refc, method, false); MethodHandle mh = MethodHandleImpl.findMethod(IMPL_TOKEN, method, true, lookupClassOrNull()); @@ -576,9 +585,11 @@ * @param refc the class or interface from which the method is accessed * @param type the type of the method, with the receiver argument omitted, and a void return type * @return the desired method handle - * @exception NoAccessException if the method does not exist or access checking fails + * @throws NoSuchMethodException if the constructor does not exist + * @throws IllegalAccessException if access checking fails + * @throws NullPointerException if any argument is null */ - public MethodHandle findConstructor(Class<?> refc, MethodType type) throws NoAccessException { + public MethodHandle findConstructor(Class<?> refc, MethodType type) throws NoSuchMethodException, IllegalAccessException { String name = "<init>"; MemberName ctor = resolveOrFail(refc, name, type, false, false, lookupClassOrNull()); assert(ctor.isConstructor()); @@ -629,10 +640,12 @@ * @param type the type of the method, with the receiver argument omitted * @param specialCaller the proposed calling class to perform the {@code invokespecial} * @return the desired method handle - * @exception NoAccessException if the method does not exist or access checking fails + * @throws NoSuchMethodException if the method does not exist + * @throws IllegalAccessException if access checking fails + * @throws NullPointerException if any argument is null */ public MethodHandle findSpecial(Class<?> refc, String name, MethodType type, - Class<?> specialCaller) throws NoAccessException { + Class<?> specialCaller) throws NoSuchMethodException, IllegalAccessException { checkSpecialCaller(specialCaller); MemberName method = resolveOrFail(refc, name, type, false, false, specialCaller); checkMethod(refc, method, false); @@ -651,9 +664,11 @@ * @param name the field's name * @param type the field's type * @return a method handle which can load values from the field - * @exception NoAccessException if access checking fails + * @throws NoSuchFieldException if the field does not exist + * @throws IllegalAccessException if access checking fails, or if the field is {@code static} + * @throws NullPointerException if any argument is null */ - public MethodHandle findGetter(Class<?> refc, String name, Class<?> type) throws NoAccessException { + public MethodHandle findGetter(Class<?> refc, String name, Class<?> type) throws NoSuchFieldException, IllegalAccessException { return makeAccessor(refc, name, type, false, false); } @@ -668,9 +683,11 @@ * @param name the field's name * @param type the field's type * @return a method handle which can store values into the field - * @exception NoAccessException if access checking fails + * @throws NoSuchFieldException if the field does not exist + * @throws IllegalAccessException if access checking fails, or if the field is {@code static} + * @throws NullPointerException if any argument is null */ - public MethodHandle findSetter(Class<?> refc, String name, Class<?> type) throws NoAccessException { + public MethodHandle findSetter(Class<?> refc, String name, Class<?> type) throws NoSuchFieldException, IllegalAccessException { return makeAccessor(refc, name, type, false, true); } @@ -684,9 +701,11 @@ * @param name the field's name * @param type the field's type * @return a method handle which can load values from the field - * @exception NoAccessException if access checking fails + * @throws NoSuchFieldException if the field does not exist + * @throws IllegalAccessException if access checking fails, or if the field is not {@code static} + * @throws NullPointerException if any argument is null */ - public MethodHandle findStaticGetter(Class<?> refc, String name, Class<?> type) throws NoAccessException { + public MethodHandle findStaticGetter(Class<?> refc, String name, Class<?> type) throws NoSuchFieldException, IllegalAccessException { return makeAccessor(refc, name, type, true, false); } @@ -700,9 +719,11 @@ * @param name the field's name * @param type the field's type * @return a method handle which can store values into the field - * @exception NoAccessException if access checking fails + * @throws NoSuchFieldException if the field does not exist + * @throws IllegalAccessException if access checking fails, or if the field is not {@code static} + * @throws NullPointerException if any argument is null */ - public MethodHandle findStaticSetter(Class<?> refc, String name, Class<?> type) throws NoAccessException { + public MethodHandle findStaticSetter(Class<?> refc, String name, Class<?> type) throws NoSuchFieldException, IllegalAccessException { return makeAccessor(refc, name, type, true, true); } @@ -741,16 +762,18 @@ * @param name the name of the method * @param type the type of the method, with the receiver argument omitted * @return the desired method handle - * @exception NoAccessException if the method does not exist or access checking fails + * @throws NoSuchMethodException if the method does not exist + * @throws IllegalAccessException if access checking fails + * @throws NullPointerException if any argument is null */ - public MethodHandle bind(Object receiver, String name, MethodType type) throws NoAccessException { + public MethodHandle bind(Object receiver, String name, MethodType type) throws NoSuchMethodException, IllegalAccessException { Class<? extends Object> refc = receiver.getClass(); // may get NPE MemberName method = resolveOrFail(refc, name, type, false); checkMethod(refc, method, false); MethodHandle dmh = MethodHandleImpl.findMethod(IMPL_TOKEN, method, true, lookupClassOrNull()); MethodHandle bmh = MethodHandleImpl.bindReceiver(IMPL_TOKEN, dmh, receiver); if (bmh == null) - throw newNoAccessException(method, lookupClass()); + throw newNoAccessException(method, this); if (dmh.type().parameterCount() == 0) return dmh; // bound the trailing parameter; no varargs possible return fixVarargs(bmh, dmh); @@ -772,9 +795,10 @@ * the method's variable arity modifier bit ({@code 0x0080}) is set. * @param m the reflected method * @return a method handle which can invoke the reflected method - * @exception NoAccessException if access checking fails + * @throws IllegalAccessException if access checking fails + * @throws NullPointerException if the argument is null */ - public MethodHandle unreflect(Method m) throws NoAccessException { + public MethodHandle unreflect(Method m) throws IllegalAccessException { MemberName method = new MemberName(m); assert(method.isMethod()); if (!m.isAccessible()) checkMethod(method.getDeclaringClass(), method, method.isStatic()); @@ -799,9 +823,10 @@ * @param m the reflected method * @param specialCaller the class nominally calling the method * @return a method handle which can invoke the reflected method - * @exception NoAccessException if access checking fails + * @throws IllegalAccessException if access checking fails + * @throws NullPointerException if any argument is null */ - public MethodHandle unreflectSpecial(Method m, Class<?> specialCaller) throws NoAccessException { + public MethodHandle unreflectSpecial(Method m, Class<?> specialCaller) throws IllegalAccessException { checkSpecialCaller(specialCaller); MemberName method = new MemberName(m); assert(method.isMethod()); @@ -827,9 +852,10 @@ * the constructor's variable arity modifier bit ({@code 0x0080}) is set. * @param c the reflected constructor * @return a method handle which can invoke the reflected constructor - * @exception NoAccessException if access checking fails + * @throws IllegalAccessException if access checking fails + * @throws NullPointerException if the argument is null */ - public MethodHandle unreflectConstructor(Constructor c) throws NoAccessException { + public MethodHandle unreflectConstructor(Constructor c) throws IllegalAccessException { MemberName ctor = new MemberName(c); assert(ctor.isConstructor()); if (!c.isAccessible()) checkAccess(c.getDeclaringClass(), ctor); @@ -849,9 +875,10 @@ * access checking is performed immediately on behalf of the lookup class. * @param f the reflected field * @return a method handle which can load values from the reflected field - * @exception NoAccessException if access checking fails + * @throws IllegalAccessException if access checking fails + * @throws NullPointerException if the argument is null */ - public MethodHandle unreflectGetter(Field f) throws NoAccessException { + public MethodHandle unreflectGetter(Field f) throws IllegalAccessException { return makeAccessor(f.getDeclaringClass(), new MemberName(f), f.isAccessible(), false); } @@ -866,40 +893,47 @@ * access checking is performed immediately on behalf of the lookup class. * @param f the reflected field * @return a method handle which can store values into the reflected field - * @exception NoAccessException if access checking fails + * @throws IllegalAccessException if access checking fails + * @throws NullPointerException if the argument is null */ - public MethodHandle unreflectSetter(Field f) throws NoAccessException { + public MethodHandle unreflectSetter(Field f) throws IllegalAccessException { return makeAccessor(f.getDeclaringClass(), new MemberName(f), f.isAccessible(), true); } /// Helper methods, all package-private. - MemberName resolveOrFail(Class<?> refc, String name, Class<?> type, boolean isStatic) throws NoAccessException { + MemberName resolveOrFail(Class<?> refc, String name, Class<?> type, boolean isStatic) throws NoSuchFieldException, IllegalAccessException { checkSymbolicClass(refc); // do this before attempting to resolve + name.getClass(); type.getClass(); // NPE int mods = (isStatic ? Modifier.STATIC : 0); - return IMPL_NAMES.resolveOrFail(new MemberName(refc, name, type, mods), true, lookupClassOrNull()); + return IMPL_NAMES.resolveOrFail(new MemberName(refc, name, type, mods), true, lookupClassOrNull(), + NoSuchFieldException.class); } - MemberName resolveOrFail(Class<?> refc, String name, MethodType type, boolean isStatic) throws NoAccessException { + MemberName resolveOrFail(Class<?> refc, String name, MethodType type, boolean isStatic) throws NoSuchMethodException, IllegalAccessException { checkSymbolicClass(refc); // do this before attempting to resolve + name.getClass(); type.getClass(); // NPE int mods = (isStatic ? Modifier.STATIC : 0); - return IMPL_NAMES.resolveOrFail(new MemberName(refc, name, type, mods), true, lookupClassOrNull()); + return IMPL_NAMES.resolveOrFail(new MemberName(refc, name, type, mods), true, lookupClassOrNull(), + NoSuchMethodException.class); } MemberName resolveOrFail(Class<?> refc, String name, MethodType type, boolean isStatic, - boolean searchSupers, Class<?> specialCaller) throws NoAccessException { + boolean searchSupers, Class<?> specialCaller) throws NoSuchMethodException, IllegalAccessException { checkSymbolicClass(refc); // do this before attempting to resolve + name.getClass(); type.getClass(); // NPE int mods = (isStatic ? Modifier.STATIC : 0); - return IMPL_NAMES.resolveOrFail(new MemberName(refc, name, type, mods), searchSupers, specialCaller); + return IMPL_NAMES.resolveOrFail(new MemberName(refc, name, type, mods), searchSupers, specialCaller, + NoSuchMethodException.class); } - void checkSymbolicClass(Class<?> refc) throws NoAccessException { + void checkSymbolicClass(Class<?> refc) throws IllegalAccessException { Class<?> caller = lookupClassOrNull(); if (caller != null && !VerifyAccess.isClassAccessible(refc, caller)) - throw newNoAccessException("symbolic reference class is not public", new MemberName(refc), caller); + throw newNoAccessException("symbolic reference class is not public", new MemberName(refc), this); } - void checkMethod(Class<?> refc, MemberName m, boolean wantStatic) throws NoAccessException { + void checkMethod(Class<?> refc, MemberName m, boolean wantStatic) throws IllegalAccessException { String message; if (m.isConstructor()) message = "expected a method, not a constructor"; @@ -909,10 +943,10 @@ message = wantStatic ? "expected a static method" : "expected a non-static method"; else { checkAccess(refc, m); return; } - throw newNoAccessException(message, m, lookupClass()); + throw newNoAccessException(message, m, this); } - void checkAccess(Class<?> refc, MemberName m) throws NoAccessException { + void checkAccess(Class<?> refc, MemberName m) throws IllegalAccessException { int allowedModes = this.allowedModes; if (allowedModes == TRUSTED) return; int mods = m.getModifiers(); @@ -927,22 +961,25 @@ && VerifyAccess.isSamePackage(m.getDeclaringClass(), lookupClass())) // Protected members can also be checked as if they were package-private. return; - throw newNoAccessException(accessFailedMessage(refc, m), m, lookupClass()); + throw newNoAccessException(accessFailedMessage(refc, m), m, this); } String accessFailedMessage(Class<?> refc, MemberName m) { Class<?> defc = m.getDeclaringClass(); int mods = m.getModifiers(); - if (!VerifyAccess.isClassAccessible(defc, lookupClass())) + // check the class first: + boolean classOK = (Modifier.isPublic(defc.getModifiers()) && + (defc == refc || + Modifier.isPublic(refc.getModifiers()))); + if (!classOK && (allowedModes & PACKAGE) != 0) { + classOK = (VerifyAccess.isClassAccessible(defc, lookupClass()) && + (defc == refc || + VerifyAccess.isClassAccessible(refc, lookupClass()))); + } + if (!classOK) return "class is not public"; - if (refc != defc && !VerifyAccess.isClassAccessible(refc, lookupClass())) - return "symbolic reference "+refc.getName()+" is not public"; if (Modifier.isPublic(mods)) return "access to public member failed"; // (how?) - else if (allowedModes == PUBLIC) - return "member is not public"; - else if (allowedModes == 0) - return "attempted member access through a non-public class"; if (Modifier.isPrivate(mods)) return "member is private"; if (Modifier.isProtected(mods)) @@ -952,17 +989,17 @@ private static final boolean ALLOW_NESTMATE_ACCESS = false; - void checkSpecialCaller(Class<?> specialCaller) throws NoAccessException { + void checkSpecialCaller(Class<?> specialCaller) throws IllegalAccessException { if (allowedModes == TRUSTED) return; if ((allowedModes & PRIVATE) == 0 || (specialCaller != lookupClass() && !(ALLOW_NESTMATE_ACCESS && VerifyAccess.isSamePackageMember(specialCaller, lookupClass())))) throw newNoAccessException("no private access for invokespecial", - new MemberName(specialCaller), lookupClass()); + new MemberName(specialCaller), this); } - MethodHandle restrictProtectedReceiver(MemberName method, MethodHandle mh) throws NoAccessException { + MethodHandle restrictProtectedReceiver(MemberName method, MethodHandle mh) throws IllegalAccessException { // The accessing class only has the right to use a protected member // on itself or a subclass. Enforce that restriction, from JVMS 5.4.4, etc. if (!method.isProtected() || method.isStatic() @@ -974,7 +1011,7 @@ else return restrictReceiver(method, mh, lookupClass()); } - MethodHandle restrictReceiver(MemberName method, MethodHandle mh, Class<?> caller) throws NoAccessException { + MethodHandle restrictReceiver(MemberName method, MethodHandle mh, Class<?> caller) throws IllegalAccessException { assert(!method.isStatic()); Class<?> defc = method.getDeclaringClass(); // receiver type of mh is too wide if (defc.isInterface() || !defc.isAssignableFrom(caller)) { @@ -988,18 +1025,18 @@ } MethodHandle makeAccessor(Class<?> refc, String name, Class<?> type, - boolean isStatic, boolean isSetter) throws NoAccessException { + boolean isStatic, boolean isSetter) throws NoSuchFieldException, IllegalAccessException { MemberName field = resolveOrFail(refc, name, type, isStatic); if (isStatic != field.isStatic()) throw newNoAccessException(isStatic ? "expected a static field" : "expected a non-static field", - field, lookupClass()); + field, this); return makeAccessor(refc, field, false, isSetter); } MethodHandle makeAccessor(Class<?> refc, MemberName field, - boolean trusted, boolean isSetter) throws NoAccessException { + boolean trusted, boolean isSetter) throws IllegalAccessException { assert(field.isField()); if (trusted) return MethodHandleImpl.accessField(IMPL_TOKEN, field, isSetter, lookupClassOrNull());
--- a/jdk/src/share/classes/java/dyn/NoAccessException.java Fri Feb 11 01:26:28 2011 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,79 +0,0 @@ -/* - * Copyright (c) 2008, 2010, 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 - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package java.dyn; - -/** - * Thrown to indicate that a caller has attempted to create a method handle - * which accesses a field, method, or class to which the caller does not have access. - * This unchecked exception is analogous to {@link IllegalAccessException}, - * which is a checked exception thrown when reflective invocation fails - * because of an access check. With method handles, this same access - * checking is performed by the {@link MethodHandles.Lookup lookup object} - * on behalf of the method handle creator, - * at the time of creation. - * @author John Rose, JSR 292 EG - * @since 1.7 - */ -public class NoAccessException extends ReflectiveOperationException { - private static final long serialVersionUID = 292L; - - /** - * Constructs a {@code NoAccessException} with no detail message. - */ - public NoAccessException() { - super(); - } - - /** - * Constructs a {@code NoAccessException} with the specified - * detail message. - * - * @param s the detail message - */ - public NoAccessException(String s) { - super(s); - } - - /** - * Constructs a {@code NoAccessException} with the specified cause. - * - * @param cause the underlying cause of the exception - */ - public NoAccessException(Throwable cause) { - super(cause); - } - - /** - * Constructs a {@code NoAccessException} with the specified - * detail message and cause. - * - * @param s the detail message - * @param cause the underlying cause of the exception - */ - public NoAccessException(String s, Throwable cause) { - super(s, cause); - } -}
--- a/jdk/src/share/classes/sun/dyn/CallSiteImpl.java Fri Feb 11 01:26:28 2011 -0800 +++ b/jdk/src/share/classes/sun/dyn/CallSiteImpl.java Fri Feb 11 01:26:32 2011 -0800 @@ -129,7 +129,7 @@ MethodType.methodType(void.class, String.class, MethodType.class, MemberName.class, int.class)); - } catch (NoAccessException ex) { + } catch (ReflectiveOperationException ex) { throw uncaughtException(ex); } }
--- a/jdk/src/share/classes/sun/dyn/FilterGeneric.java Fri Feb 11 01:26:28 2011 -0800 +++ b/jdk/src/share/classes/sun/dyn/FilterGeneric.java Fri Feb 11 01:26:32 2011 -0800 @@ -187,7 +187,7 @@ MethodHandle entryPoint = null; try { entryPoint = MethodHandleImpl.IMPL_LOOKUP.findSpecial(acls, iname, entryType, acls); - } catch (NoAccessException ex) { + } catch (ReflectiveOperationException ex) { } if (entryPoint == null) continue; Constructor<? extends Adapter> ctor = null;
--- a/jdk/src/share/classes/sun/dyn/FilterOneArgument.java Fri Feb 11 01:26:28 2011 -0800 +++ b/jdk/src/share/classes/sun/dyn/FilterOneArgument.java Fri Feb 11 01:26:32 2011 -0800 @@ -56,7 +56,7 @@ INVOKE = MethodHandleImpl.IMPL_LOOKUP.findVirtual(FilterOneArgument.class, "invoke", MethodType.genericMethodType(1)); - } catch (NoAccessException ex) { + } catch (ReflectiveOperationException ex) { throw uncaughtException(ex); } }
--- a/jdk/src/share/classes/sun/dyn/FromGeneric.java Fri Feb 11 01:26:28 2011 -0800 +++ b/jdk/src/share/classes/sun/dyn/FromGeneric.java Fri Feb 11 01:26:32 2011 -0800 @@ -204,7 +204,7 @@ MethodHandle entryPoint = null; try { entryPoint = MethodHandleImpl.IMPL_LOOKUP.findSpecial(acls, iname, entryType, acls); - } catch (NoAccessException ex) { + } catch (ReflectiveOperationException ex) { } if (entryPoint == null) continue; Constructor<? extends Adapter> ctor = null;
--- a/jdk/src/share/classes/sun/dyn/InvokeGeneric.java Fri Feb 11 01:26:28 2011 -0800 +++ b/jdk/src/share/classes/sun/dyn/InvokeGeneric.java Fri Feb 11 01:26:32 2011 -0800 @@ -44,7 +44,7 @@ /** Compute and cache information for this adapter, so that it can * call out to targets of the erasure-family of the given erased type. */ - private InvokeGeneric(MethodType erasedCallerType) throws NoAccessException { + private InvokeGeneric(MethodType erasedCallerType) throws ReflectiveOperationException { this.erasedCallerType = erasedCallerType; this.initialInvoker = makeInitialInvoker(); assert initialInvoker.type().equals(erasedCallerType @@ -64,14 +64,14 @@ try { InvokeGeneric gen = new InvokeGeneric(form.erasedType()); form.genericInvoker = genericInvoker = gen.initialInvoker; - } catch (NoAccessException ex) { + } catch (ReflectiveOperationException ex) { throw new RuntimeException(ex); } } return genericInvoker; } - private MethodHandle makeInitialInvoker() throws NoAccessException { + private MethodHandle makeInitialInvoker() throws ReflectiveOperationException { // postDispatch = #(MH'; MT, MH; A...){MH'(MT, MH; A)} MethodHandle postDispatch = makePostDispatchInvoker(); MethodHandle invoker; @@ -95,7 +95,7 @@ return MethodHandles.dropArguments(targetInvoker, 1, EXTRA_ARGS); } - private MethodHandle dispatcher(String dispatchName) throws NoAccessException { + private MethodHandle dispatcher(String dispatchName) throws ReflectiveOperationException { return lookup().bind(this, dispatchName, MethodType.methodType(MethodHandle.class, MethodType.class, MethodHandle.class));
--- a/jdk/src/share/classes/sun/dyn/Invokers.java Fri Feb 11 01:26:28 2011 -0800 +++ b/jdk/src/share/classes/sun/dyn/Invokers.java Fri Feb 11 01:26:32 2011 -0800 @@ -69,7 +69,7 @@ if (invoker != null) return invoker; try { invoker = MethodHandleImpl.IMPL_LOOKUP.findVirtual(MethodHandle.class, "invokeExact", targetType); - } catch (NoAccessException ex) { + } catch (ReflectiveOperationException ex) { throw new InternalError("JVM cannot find invoker for "+targetType); } assert(invokerType(targetType) == invoker.type()); @@ -128,7 +128,7 @@ THROW_UCS = MethodHandleImpl.IMPL_LOOKUP .findStatic(CallSite.class, "uninitializedCallSite", MethodType.methodType(Empty.class)); - } catch (NoAccessException ex) { + } catch (ReflectiveOperationException ex) { throw new RuntimeException(ex); } }
--- a/jdk/src/share/classes/sun/dyn/MemberName.java Fri Feb 11 01:26:28 2011 -0800 +++ b/jdk/src/share/classes/sun/dyn/MemberName.java Fri Feb 11 01:26:32 2011 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2011, 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 @@ -451,8 +451,6 @@ return type.toString(); // class java.lang.String // else it is a field, method, or constructor StringBuilder buf = new StringBuilder(); - if (!isResolved()) - buf.append("*."); if (getDeclaringClass() != null) { buf.append(getName(clazz)); buf.append('.'); @@ -512,14 +510,24 @@ public static RuntimeException newIllegalArgumentException(String message) { return new IllegalArgumentException(message); } - public static NoAccessException newNoAccessException(MemberName name, Class<?> lookupClass) { - return newNoAccessException("cannot access", name, lookupClass); + public static IllegalAccessException newNoAccessException(MemberName name, Object from) { + return newNoAccessException("cannot access", name, from); + } + public static IllegalAccessException newNoAccessException(String message, + MemberName name, Object from) { + message += ": " + name; + if (from != null) message += ", from " + from; + return new IllegalAccessException(message); } - public static NoAccessException newNoAccessException(String message, - MemberName name, Class<?> lookupClass) { - message += ": " + name; - if (lookupClass != null) message += ", from " + lookupClass.getName(); - return new NoAccessException(message); + public static ReflectiveOperationException newNoAccessException(MemberName name) { + if (name.isResolved()) + return new IllegalAccessException(name.toString()); + else if (name.isConstructor()) + return new NoSuchMethodException(name.toString()); + else if (name.isMethod()) + return new NoSuchMethodException(name.toString()); + else + return new NoSuchFieldException(name.toString()); } public static Error uncaughtException(Exception ex) { Error err = new InternalError("uncaught exception"); @@ -643,14 +651,20 @@ /** 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, a {@linkplain NoAccessException} is thrown. + * If lookup fails or access is not permitted, a {@linkplain ReflectiveOperationException} is thrown. * Otherwise a fresh copy of the given member is returned, with modifier bits filled in. */ - public MemberName resolveOrFail(MemberName m, boolean searchSupers, Class<?> lookupClass) throws NoAccessException { + public + <NoSuchMemberException extends ReflectiveOperationException> + MemberName resolveOrFail(MemberName m, boolean searchSupers, Class<?> lookupClass, + Class<NoSuchMemberException> nsmClass) + throws IllegalAccessException, NoSuchMemberException { MemberName result = resolveOrNull(m, searchSupers, lookupClass); if (result != null) return result; - throw newNoAccessException(m, lookupClass); + ReflectiveOperationException ex = newNoAccessException(m); + if (ex instanceof IllegalAccessException) throw (IllegalAccessException) ex; + throw nsmClass.cast(ex); } /** Return a list of all methods defined by the given class. * Super types are searched (for inherited members) if {@code searchSupers} is true.
--- a/jdk/src/share/classes/sun/dyn/MethodHandleImpl.java Fri Feb 11 01:26:28 2011 -0800 +++ b/jdk/src/share/classes/sun/dyn/MethodHandleImpl.java Fri Feb 11 01:26:32 2011 -0800 @@ -30,7 +30,6 @@ import java.util.logging.Level; import java.util.logging.Logger; import sun.dyn.util.VerifyType; -import java.dyn.NoAccessException; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; @@ -169,11 +168,11 @@ * @param doDispatch whether the method handle will test the receiver type * @param lookupClass access-check relative to this class * @return a direct handle to the matching method - * @throws NoAccessException if the given method cannot be accessed by the lookup class + * @throws IllegalAccessException if the given method cannot be accessed by the lookup class */ public static MethodHandle findMethod(Access token, MemberName method, - boolean doDispatch, Class<?> lookupClass) throws NoAccessException { + boolean doDispatch, Class<?> lookupClass) throws IllegalAccessException { Access.check(token); // only trusted calls MethodType mtype = method.getMethodType(); if (!method.isStatic()) { @@ -307,7 +306,7 @@ MethodHandle invoke = null; try { invoke = lookup.findVirtual(AllocateObject.class, name, MethodType.genericMethodType(nargs)); - } catch (NoAccessException ex) { + } catch (ReflectiveOperationException ex) { } if (invoke == null) break; invokes.add(invoke); @@ -322,7 +321,7 @@ static { try { VARARGS_INVOKE = IMPL_LOOKUP.findVirtual(AllocateObject.class, "invoke_V", MethodType.genericMethodType(0, true)); - } catch (NoAccessException ex) { + } catch (ReflectiveOperationException ex) { throw uncaughtException(ex); } } @@ -474,7 +473,7 @@ MethodHandle mh; try { mh = IMPL_LOOKUP.findVirtual(FieldAccessor.class, name, type); - } catch (NoAccessException ex) { + } catch (ReflectiveOperationException ex) { throw uncaughtException(ex); } if (evclass != vclass || (!isStatic && ecclass != cclass)) { @@ -542,7 +541,7 @@ MethodHandle mh; try { mh = IMPL_LOOKUP.findStatic(FieldAccessor.class, name, type); - } catch (NoAccessException ex) { + } catch (ReflectiveOperationException ex) { throw uncaughtException(ex); } if (caclass != null) { @@ -1014,7 +1013,7 @@ MethodHandle invoke = null; try { invoke = lookup.findVirtual(GuardWithTest.class, name, MethodType.genericMethodType(nargs)); - } catch (NoAccessException ex) { + } catch (ReflectiveOperationException ex) { } if (invoke == null) break; invokes.add(invoke); @@ -1029,7 +1028,7 @@ static { try { VARARGS_INVOKE = IMPL_LOOKUP.findVirtual(GuardWithTest.class, "invoke_V", MethodType.genericMethodType(0, true)); - } catch (NoAccessException ex) { + } catch (ReflectiveOperationException ex) { throw uncaughtException(ex); } } @@ -1150,7 +1149,7 @@ MethodHandle invoke = null; try { invoke = lookup.findVirtual(GuardWithCatch.class, name, MethodType.genericMethodType(nargs)); - } catch (NoAccessException ex) { + } catch (ReflectiveOperationException ex) { } if (invoke == null) break; invokes.add(invoke); @@ -1165,7 +1164,7 @@ static { try { VARARGS_INVOKE = IMPL_LOOKUP.findVirtual(GuardWithCatch.class, "invoke_V", MethodType.genericMethodType(0, true)); - } catch (NoAccessException ex) { + } catch (ReflectiveOperationException ex) { throw uncaughtException(ex); } } @@ -1212,7 +1211,7 @@ THROW_EXCEPTION = IMPL_LOOKUP.findStatic(MethodHandleImpl.class, "throwException", MethodType.methodType(Empty.class, Throwable.class)); - } catch (NoAccessException ex) { + } catch (ReflectiveOperationException ex) { throw new RuntimeException(ex); } }
--- a/jdk/src/share/classes/sun/dyn/MethodHandleNatives.java Fri Feb 11 01:26:28 2011 -0800 +++ b/jdk/src/share/classes/sun/dyn/MethodHandleNatives.java Fri Feb 11 01:26:32 2011 -0800 @@ -350,7 +350,7 @@ case REF_invokeInterface: return lookup.findVirtual( defc, name, (MethodType) type ); } throw new IllegalArgumentException("bad MethodHandle constant "+name+" : "+type); - } catch (NoAccessException ex) { + } catch (ReflectiveOperationException ex) { Error err = new IncompatibleClassChangeError(); err.initCause(ex); throw err;
--- a/jdk/src/share/classes/sun/dyn/SpreadGeneric.java Fri Feb 11 01:26:28 2011 -0800 +++ b/jdk/src/share/classes/sun/dyn/SpreadGeneric.java Fri Feb 11 01:26:32 2011 -0800 @@ -167,7 +167,7 @@ MethodHandle entryPoint = null; try { entryPoint = MethodHandleImpl.IMPL_LOOKUP.findSpecial(acls, iname, entryType, acls); - } catch (NoAccessException ex) { + } catch (ReflectiveOperationException ex) { } if (entryPoint == null) continue; Constructor<? extends Adapter> ctor = null;
--- a/jdk/src/share/classes/sun/dyn/ToGeneric.java Fri Feb 11 01:26:28 2011 -0800 +++ b/jdk/src/share/classes/sun/dyn/ToGeneric.java Fri Feb 11 01:26:32 2011 -0800 @@ -285,7 +285,7 @@ try { entryPoint = MethodHandleImpl.IMPL_LOOKUP. findSpecial(acls, iname, entryPointType, acls); - } catch (NoAccessException ex) { + } catch (ReflectiveOperationException ex) { } if (entryPoint == null) continue; Constructor<? extends Adapter> ctor = null;
--- a/jdk/src/share/classes/sun/dyn/util/ValueConversions.java Fri Feb 11 01:26:28 2011 -0800 +++ b/jdk/src/share/classes/sun/dyn/util/ValueConversions.java Fri Feb 11 01:26:32 2011 -0800 @@ -153,7 +153,7 @@ try { // actually, type is wrong; the Java method takes Object mh = IMPL_LOOKUP.findStatic(ValueConversions.class, name, type.erase()); - } catch (NoAccessException ex) { + } catch (ReflectiveOperationException ex) { mh = null; } } else { @@ -289,7 +289,7 @@ if (exact) { try { mh = IMPL_LOOKUP.findStatic(ValueConversions.class, name, type); - } catch (NoAccessException ex) { + } catch (ReflectiveOperationException ex) { mh = null; } } else { @@ -408,7 +408,7 @@ if (exact) { try { mh = IMPL_LOOKUP.findStatic(ValueConversions.class, name, type); - } catch (NoAccessException ex) { + } catch (ReflectiveOperationException ex) { mh = null; } } else { @@ -492,7 +492,7 @@ case INT: case LONG: case FLOAT: case DOUBLE: try { mh = IMPL_LOOKUP.findStatic(ValueConversions.class, "zero"+wrap.simpleName(), type); - } catch (NoAccessException ex) { + } catch (ReflectiveOperationException ex) { mh = null; } break; @@ -654,7 +654,7 @@ type = type.appendParameterTypes(wrap.primitiveType()); try { mh = IMPL_LOOKUP.findStatic(ValueConversions.class, "identity", type); - } catch (NoAccessException ex) { + } catch (ReflectiveOperationException ex) { mh = null; } if (mh == null && wrap == Wrapper.VOID) { @@ -723,7 +723,7 @@ MethodHandle array = null; try { array = lookup.findStatic(ValueConversions.class, name, type); - } catch (NoAccessException ex) { + } catch (ReflectiveOperationException ex) { } if (array == null) break; arrays.add(array); @@ -784,7 +784,7 @@ MethodHandle array = null; try { array = lookup.findStatic(ValueConversions.class, name, type); - } catch (NoAccessException ex) { + } catch (ReflectiveOperationException ex) { } if (array == null) break; arrays.add(array);
--- a/jdk/src/share/classes/sun/dyn/util/VerifyAccess.java Fri Feb 11 01:26:28 2011 -0800 +++ b/jdk/src/share/classes/sun/dyn/util/VerifyAccess.java Fri Feb 11 01:26:32 2011 -0800 @@ -25,7 +25,6 @@ package sun.dyn.util; -import java.dyn.NoAccessException; import java.lang.reflect.Modifier; import sun.dyn.MemberName; import sun.dyn.MethodHandleImpl; @@ -139,6 +138,8 @@ * <li>C is public. * <li>C and D are members of the same runtime package. * </ul> + * @param refc the symbolic reference class to which access is being checked (C) + * @param lookupClass the class performing the lookup (D) */ public static boolean isClassAccessible(Class<?> refc, Class<?> lookupClass) { int mods = refc.getModifiers();
--- a/jdk/test/java/dyn/InvokeGenericTest.java Fri Feb 11 01:26:28 2011 -0800 +++ b/jdk/test/java/dyn/InvokeGenericTest.java Fri Feb 11 01:26:32 2011 -0800 @@ -338,7 +338,7 @@ = LOOKUP.findStatic(LOOKUP.lookupClass(), "collector", methodType(Object.class, Object[].class)); - } catch (NoAccessException ex) { + } catch (ReflectiveOperationException ex) { throw new RuntimeException(ex); } }
--- a/jdk/test/java/dyn/JavaDocExamplesTest.java Fri Feb 11 01:26:28 2011 -0800 +++ b/jdk/test/java/dyn/JavaDocExamplesTest.java Fri Feb 11 01:26:32 2011 -0800 @@ -74,7 +74,7 @@ // static final private MethodHandle HASHCODE_1 = LOOKUP.findVirtual(Object.class, // "hashCode", methodType(int.class)); -// form required if NoAccessException is intercepted: +// form required if ReflectiveOperationException is intercepted: static final private MethodHandle CONCAT_2, HASHCODE_2; static { try { @@ -82,7 +82,7 @@ "concat", methodType(String.class, String.class)); HASHCODE_2 = LOOKUP.findVirtual(Object.class, "hashCode", methodType(int.class)); - } catch (NoAccessException ex) { + } catch (ReflectiveOperationException ex) { throw new RuntimeException(ex); } }
--- a/jdk/test/java/dyn/MethodHandlesTest.java Fri Feb 11 01:26:28 2011 -0800 +++ b/jdk/test/java/dyn/MethodHandlesTest.java Fri Feb 11 01:26:32 2011 -0800 @@ -496,8 +496,12 @@ try { if (verbosity >= 4) System.out.println("lookup via "+lookup+" of "+defc+" "+name+type); target = lookup.in(defc).findStatic(defc, name, type); - } catch (NoAccessException ex) { + } catch (ReflectiveOperationException ex) { noAccess = ex; + if (name.contains("bogus")) + assertTrue(noAccess instanceof NoSuchMethodException); + else + assertTrue(noAccess instanceof IllegalAccessException); } if (verbosity >= 3) System.out.println("findStatic "+lookup+": "+defc.getName()+"."+name+"/"+type+" => "+target @@ -566,8 +570,12 @@ try { if (verbosity >= 4) System.out.println("lookup via "+lookup+" of "+defc+" "+name+type); target = lookup.in(defc).findVirtual(defc, methodName, type); - } catch (NoAccessException ex) { + } catch (ReflectiveOperationException ex) { noAccess = ex; + if (name.contains("bogus")) + assertTrue(noAccess instanceof NoSuchMethodException); + else + assertTrue(noAccess instanceof IllegalAccessException); } if (verbosity >= 3) System.out.println("findVirtual "+lookup+": "+defc.getName()+"."+name+"/"+type+" => "+target @@ -596,11 +604,12 @@ testFindSpecial(SubExample.class, Example.class, void.class, "v0"); testFindSpecial(SubExample.class, Example.class, void.class, "pkg_v0"); // Do some negative testing: + testFindSpecial(false, EXAMPLE, SubExample.class, Example.class, void.class, "bogus"); + testFindSpecial(false, PRIVATE, SubExample.class, Example.class, void.class, "bogus"); for (Lookup lookup : new Lookup[]{ PRIVATE, EXAMPLE, PACKAGE, PUBLIC }) { testFindSpecial(false, lookup, Object.class, Example.class, void.class, "v0"); testFindSpecial(false, lookup, SubExample.class, Example.class, void.class, "<init>", int.class); testFindSpecial(false, lookup, SubExample.class, Example.class, void.class, "s0"); - testFindSpecial(false, lookup, SubExample.class, Example.class, void.class, "bogus"); } } @@ -621,8 +630,12 @@ if (verbosity >= 4) System.out.println("lookup via "+lookup+" of "+defc+" "+name+type); if (verbosity >= 5) System.out.println(" lookup => "+lookup.in(specialCaller)); target = lookup.in(specialCaller).findSpecial(defc, name, type, specialCaller); - } catch (NoAccessException ex) { + } catch (ReflectiveOperationException ex) { noAccess = ex; + if (name.contains("bogus")) + assertTrue(noAccess instanceof NoSuchMethodException); + else + assertTrue(noAccess instanceof IllegalAccessException); } if (verbosity >= 3) System.out.println("findSpecial from "+specialCaller.getName()+" to "+defc.getName()+"."+name+"/"+type+" => "+target @@ -677,8 +690,12 @@ try { if (verbosity >= 4) System.out.println("lookup via "+lookup+" of "+defc+" "+name+type); target = lookup.in(defc).bind(receiver, methodName, type); - } catch (NoAccessException ex) { + } catch (ReflectiveOperationException ex) { noAccess = ex; + if (name.contains("bogus")) + assertTrue(noAccess instanceof NoSuchMethodException); + else + assertTrue(noAccess instanceof IllegalAccessException); } if (verbosity >= 3) System.out.println("bind "+receiver+"."+name+"/"+type+" => "+target @@ -736,14 +753,9 @@ Class<?> defc, Class<?> rcvc, Class<?> ret, String name, Class<?>... params) throws Throwable { countTest(positive); MethodType type = MethodType.methodType(ret, params); - Method rmethod = null; + Method rmethod = defc.getDeclaredMethod(name, params); MethodHandle target = null; Exception noAccess = null; - try { - rmethod = defc.getDeclaredMethod(name, params); - } catch (NoSuchMethodException ex) { - throw new NoAccessException(ex); - } boolean isStatic = (rcvc == null); boolean isSpecial = (specialCaller != null); try { @@ -752,8 +764,12 @@ target = lookup.in(specialCaller).unreflectSpecial(rmethod, specialCaller); else target = lookup.in(defc).unreflect(rmethod); - } catch (NoAccessException ex) { + } catch (ReflectiveOperationException ex) { noAccess = ex; + if (name.contains("bogus")) + assertTrue(noAccess instanceof NoSuchMethodException); + else + assertTrue(noAccess instanceof IllegalAccessException); } if (verbosity >= 3) System.out.println("unreflect"+(isSpecial?"Special":"")+" "+defc.getName()+"."+name+"/"+type @@ -862,25 +878,28 @@ if (type == float.class) { float v = 'F'; if (isStatic) v++; - assert(value.equals(v)); + assertTrue(value.equals(v)); } - assert(name.equals(field.getName())); - assert(type.equals(field.getType())); - assert(isStatic == (Modifier.isStatic(field.getModifiers()))); + assertTrue(name.equals(field.getName())); + assertTrue(type.equals(field.getType())); + assertTrue(isStatic == (Modifier.isStatic(field.getModifiers()))); cases.add(new Object[]{ field, value }); } } + cases.add(new Object[]{ new Object[]{ false, HasFields.class, "bogus_fD", double.class }, Error.class }); + cases.add(new Object[]{ new Object[]{ true, HasFields.class, "bogus_sL", Object.class }, Error.class }); CASES = cases.toArray(new Object[0][]); } } - static final int TEST_UNREFLECT = 1, TEST_FIND_FIELD = 2, TEST_FIND_STATIC_FIELD = 3; + static final int TEST_UNREFLECT = 1, TEST_FIND_FIELD = 2, TEST_FIND_STATIC = 3, TEST_SETTER = 0x10; static boolean testModeMatches(int testMode, boolean isStatic) { switch (testMode) { - case TEST_FIND_STATIC_FIELD: return isStatic; + case TEST_FIND_STATIC: return isStatic; case TEST_FIND_FIELD: return !isStatic; - default: return true; // unreflect matches both + case TEST_UNREFLECT: return true; // unreflect matches both } + throw new InternalError("testMode="+testMode); } @Test @@ -896,54 +915,161 @@ @Test public void testFindStaticGetter() throws Throwable { startTest("findStaticGetter"); - testGetter(TEST_FIND_STATIC_FIELD); + testGetter(TEST_FIND_STATIC); } public void testGetter(int testMode) throws Throwable { Lookup lookup = PRIVATE; // FIXME: test more lookups than this one for (Object[] c : HasFields.CASES) { - Field f = (Field)c[0]; - Object value = c[1]; - Class<?> type = f.getType(); - testGetter(lookup, f, type, value, testMode); + boolean positive = (c[1] != Error.class); + testGetter(positive, lookup, c[0], c[1], testMode); + } + testGetter(true, lookup, + new Object[]{ true, System.class, "out", java.io.PrintStream.class }, + System.out, testMode); + for (int isStaticN = 0; isStaticN <= 1; isStaticN++) { + testGetter(false, lookup, + new Object[]{ (isStaticN != 0), System.class, "bogus", char.class }, + null, testMode); } } - public void testGetter(MethodHandles.Lookup lookup, - Field f, Class<?> type, Object value, int testMode) throws Throwable { - boolean isStatic = Modifier.isStatic(f.getModifiers()); - Class<?> fclass = f.getDeclaringClass(); - String fname = f.getName(); - Class<?> ftype = f.getType(); + public void testGetter(boolean positive, MethodHandles.Lookup lookup, + Object fieldRef, Object value, int testMode) throws Throwable { + testAccessor(positive, lookup, fieldRef, value, testMode); + } + + public void testAccessor(boolean positive, MethodHandles.Lookup lookup, + Object fieldRef, Object value, int testMode0) throws Throwable { + boolean isGetter = ((testMode0 & TEST_SETTER) == 0); + int testMode = testMode0 & ~TEST_SETTER; + boolean isStatic; + Class<?> fclass; + String fname; + Class<?> ftype; + Field f = (fieldRef instanceof Field ? (Field)fieldRef : null); + if (f != null) { + isStatic = Modifier.isStatic(f.getModifiers()); + fclass = f.getDeclaringClass(); + fname = f.getName(); + ftype = f.getType(); + } else { + Object[] scnt = (Object[]) fieldRef; + isStatic = (Boolean) scnt[0]; + fclass = (Class<?>) scnt[1]; + fname = (String) scnt[2]; + ftype = (Class<?>) scnt[3]; + try { + f = fclass.getDeclaredField(fname); + } catch (ReflectiveOperationException ex) { + f = null; + } + } if (!testModeMatches(testMode, isStatic)) return; - countTest(true); - MethodType expType = MethodType.methodType(type, HasFields.class); + if (f == null && testMode == TEST_UNREFLECT) return; + countTest(positive); + MethodType expType; + if (isGetter) + expType = MethodType.methodType(ftype, HasFields.class); + else + expType = MethodType.methodType(void.class, HasFields.class, ftype); if (isStatic) expType = expType.dropParameterTypes(0, 1); - MethodHandle mh = lookup.unreflectGetter(f); + Exception noAccess = null; + MethodHandle mh; + try { + switch (testMode0) { + case TEST_UNREFLECT: mh = lookup.unreflectGetter(f); break; + case TEST_FIND_FIELD: mh = lookup.findGetter(fclass, fname, ftype); break; + case TEST_FIND_STATIC: mh = lookup.findStaticGetter(fclass, fname, ftype); break; + case TEST_SETTER| + TEST_UNREFLECT: mh = lookup.unreflectSetter(f); break; + case TEST_SETTER| + TEST_FIND_FIELD: mh = lookup.findSetter(fclass, fname, ftype); break; + case TEST_SETTER| + TEST_FIND_STATIC: mh = lookup.findStaticSetter(fclass, fname, ftype); break; + default: + throw new InternalError("testMode="+testMode); + } + } catch (ReflectiveOperationException ex) { + mh = null; + noAccess = ex; + if (fname.contains("bogus")) + assertTrue(noAccess instanceof NoSuchFieldException); + else + assertTrue(noAccess instanceof IllegalAccessException); + } + if (verbosity >= 3) + System.out.println("find"+(isStatic?"Static":"")+(isGetter?"Getter":"Setter")+" "+fclass.getName()+"."+fname+"/"+ftype + +" => "+mh + +(noAccess == null ? "" : " !! "+noAccess)); + if (positive && noAccess != null) throw new RuntimeException(noAccess); + assertEquals(positive ? "positive test" : "negative test erroneously passed", positive, mh != null); + if (!positive) return; // negative test failed as expected + assertEquals((isStatic ? 0 : 1)+(isGetter ? 0 : 1), mh.type().parameterCount()); + + assertSame(mh.type(), expType); assertNameStringContains(mh, fname); HasFields fields = new HasFields(); Object sawValue; - Class<?> rtype = type; - if (type != int.class) rtype = Object.class; - mh = MethodHandles.convertArguments(mh, mh.type().generic().changeReturnType(rtype)); - Object expValue = value; - for (int i = 0; i <= 1; i++) { - if (isStatic) { - if (type == int.class) - sawValue = (int) mh.invokeExact(); // do these exactly - else - sawValue = mh.invokeExact(); - } else { - if (type == int.class) - sawValue = (int) mh.invokeExact((Object) fields); - else - sawValue = mh.invokeExact((Object) fields); + Class<?> vtype = ftype; + if (ftype != int.class) vtype = Object.class; + if (isGetter) { + mh = MethodHandles.convertArguments(mh, mh.type().generic() + .changeReturnType(vtype)); + } else { + int last = mh.type().parameterCount() - 1; + mh = MethodHandles.convertArguments(mh, mh.type().generic() + .changeReturnType(void.class) + .changeParameterType(last, vtype)); + } + if (f != null && f.getDeclaringClass() == HasFields.class) { + assertEquals(f.get(fields), value); // clean to start with + } + if (isGetter) { + Object expValue = value; + for (int i = 0; i <= 1; i++) { + if (isStatic) { + if (ftype == int.class) + sawValue = (int) mh.invokeExact(); // do these exactly + else + sawValue = mh.invokeExact(); + } else { + if (ftype == int.class) + sawValue = (int) mh.invokeExact((Object) fields); + else + sawValue = mh.invokeExact((Object) fields); + } + assertEquals(sawValue, expValue); + if (f != null && f.getDeclaringClass() == HasFields.class + && !Modifier.isFinal(f.getModifiers())) { + Object random = randomArg(ftype); + f.set(fields, random); + expValue = random; + } else { + break; + } } - assertEquals(sawValue, expValue); - Object random = randomArg(type); - f.set(fields, random); - expValue = random; + } else { + for (int i = 0; i <= 1; i++) { + Object putValue = randomArg(ftype); + if (isStatic) { + if (ftype == int.class) + mh.invokeExact((int)putValue); // do these exactly + else + mh.invokeExact(putValue); + } else { + if (ftype == int.class) + mh.invokeExact((Object) fields, (int)putValue); + else + mh.invokeExact((Object) fields, putValue); + } + if (f != null && f.getDeclaringClass() == HasFields.class) { + assertEquals(f.get(fields), putValue); + } + } } - f.set(fields, value); // put it back + if (f != null && f.getDeclaringClass() == HasFields.class) { + f.set(fields, value); // put it back + } } @@ -960,61 +1086,24 @@ @Test public void testFindStaticSetter() throws Throwable { startTest("findStaticSetter"); - testSetter(TEST_FIND_STATIC_FIELD); + testSetter(TEST_FIND_STATIC); } public void testSetter(int testMode) throws Throwable { Lookup lookup = PRIVATE; // FIXME: test more lookups than this one startTest("unreflectSetter"); for (Object[] c : HasFields.CASES) { - Field f = (Field)c[0]; - Object value = c[1]; - Class<?> type = f.getType(); - testSetter(lookup, f, type, value, testMode); + boolean positive = (c[1] != Error.class); + testSetter(positive, lookup, c[0], c[1], testMode); + } + for (int isStaticN = 0; isStaticN <= 1; isStaticN++) { + testSetter(false, lookup, + new Object[]{ (isStaticN != 0), System.class, "bogus", char.class }, + null, testMode); } } - public void testSetter(MethodHandles.Lookup lookup, - Field f, Class<?> type, Object value, int testMode) throws Throwable { - boolean isStatic = Modifier.isStatic(f.getModifiers()); - Class<?> fclass = f.getDeclaringClass(); - String fname = f.getName(); - Class<?> ftype = f.getType(); - if (!testModeMatches(testMode, isStatic)) return; - countTest(true); - MethodType expType = MethodType.methodType(void.class, HasFields.class, type); - if (isStatic) expType = expType.dropParameterTypes(0, 1); - MethodHandle mh; - if (testMode == TEST_UNREFLECT) - mh = lookup.unreflectSetter(f); - else if (testMode == TEST_FIND_FIELD) - mh = lookup.findSetter(fclass, fname, ftype); - else if (testMode == TEST_FIND_STATIC_FIELD) - mh = lookup.findStaticSetter(fclass, fname, ftype); - else throw new InternalError(); - assertSame(mh.type(), expType); - assertNameStringContains(mh, fname); - HasFields fields = new HasFields(); - Object sawValue; - Class<?> vtype = type; - if (type != int.class) vtype = Object.class; - int last = mh.type().parameterCount() - 1; - mh = MethodHandles.convertArguments(mh, mh.type().generic().changeReturnType(void.class).changeParameterType(last, vtype)); - assertEquals(f.get(fields), value); // clean to start with - for (int i = 0; i <= 1; i++) { - Object putValue = randomArg(type); - if (isStatic) { - if (type == int.class) - mh.invokeExact((int)putValue); // do these exactly - else - mh.invokeExact(putValue); - } else { - if (type == int.class) - mh.invokeExact((Object) fields, (int)putValue); - else - mh.invokeExact((Object) fields, putValue); - } - assertEquals(f.get(fields), putValue); - } - f.set(fields, value); // put it back + public void testSetter(boolean positive, MethodHandles.Lookup lookup, + Object fieldRef, Object value, int testMode) throws Throwable { + testAccessor(positive, lookup, fieldRef, value, testMode | TEST_SETTER); } @Test @@ -1323,7 +1412,7 @@ types[i] = args[i].getClass(); } int inargs = args.length, outargs = reorder.length; - assert(inargs == types.length); + assertTrue(inargs == types.length); if (verbosity >= 3) System.out.println("permuteArguments "+Arrays.toString(reorder)); Object[] permArgs = new Object[outargs]; @@ -2219,12 +2308,13 @@ MethodHandle array = null; try { array = lookup.findStatic(ValueConversions.class, name, type); - } catch (NoAccessException ex) { + } catch (ReflectiveOperationException ex) { + // break from loop! } if (array == null) break; arrays.add(array); } - assert(arrays.size() == 11); // current number of methods + assertTrue(arrays.size() == 11); // current number of methods return arrays.toArray(new MethodHandle[0]); } static final MethodHandle[] ARRAYS = makeArrays(); @@ -2280,12 +2370,13 @@ MethodHandle list = null; try { list = lookup.findStatic(ValueConversions.class, name, type); - } catch (NoAccessException ex) { + } catch (ReflectiveOperationException ex) { + // break from loop! } if (list == null) break; lists.add(list); } - assert(lists.size() == 11); // current number of methods + assertTrue(lists.size() == 11); // current number of methods return lists.toArray(new MethodHandle[0]); } static final MethodHandle[] LISTS = makeLists();