--- a/jdk/src/share/classes/java/lang/invoke/MethodHandles.java Sat Oct 05 05:30:38 2013 -0700
+++ b/jdk/src/share/classes/java/lang/invoke/MethodHandles.java Sat Oct 05 05:30:38 2013 -0700
@@ -1204,6 +1204,26 @@
int allowedModes = this.allowedModes;
if (allowedModes == TRUSTED) return;
int mods = m.getModifiers();
+ if (Modifier.isProtected(mods) &&
+ refKind == REF_invokeVirtual &&
+ m.getDeclaringClass() == Object.class &&
+ m.getName().equals("clone") &&
+ refc.isArray()) {
+ // The JVM does this hack also.
+ // (See ClassVerifier::verify_invoke_instructions
+ // and LinkResolver::check_method_accessability.)
+ // Because the JVM does not allow separate methods on array types,
+ // there is no separate method for int[].clone.
+ // All arrays simply inherit Object.clone.
+ // But for access checking logic, we make Object.clone
+ // (normally protected) appear to be public.
+ // Later on, when the DirectMethodHandle is created,
+ // its leading argument will be restricted to the
+ // requested array type.
+ // N.B. The return type is not adjusted, because
+ // that is *not* the bytecode behavior.
+ mods ^= Modifier.PROTECTED | Modifier.PUBLIC;
+ }
if (Modifier.isFinal(mods) &&
MethodHandleNatives.refKindIsSetter(refKind))
throw m.makeAccessException("unexpected set of a final field", this);