changeset 5699:9d15b81d5d1b

8016839: JSR292: AME instead of IAE when calling a method Summary: Catch missing-because-illegal case for itable entries and use an exception-throwing method instead of null. Reviewed-by: acorn, jrose, coleenp
author drchase
date Tue, 26 Nov 2013 18:16:04 -0500
parents e51d73189692
children 2315fab779ca
files src/share/vm/classfile/systemDictionary.hpp src/share/vm/classfile/vmSymbols.hpp src/share/vm/memory/universe.cpp src/share/vm/memory/universe.hpp src/share/vm/oops/klassVtable.cpp test/compiler/jsr292/methodHandleExceptions/ByteClassLoader.java test/compiler/jsr292/methodHandleExceptions/C.java test/compiler/jsr292/methodHandleExceptions/I.java test/compiler/jsr292/methodHandleExceptions/TestAMEnotNPE.java test/compiler/jsr292/methodHandleExceptions/p/C.java test/compiler/jsr292/methodHandleExceptions/p/Dok.java test/compiler/jsr292/methodHandleExceptions/p/E.java test/compiler/jsr292/methodHandleExceptions/p/F.java test/compiler/jsr292/methodHandleExceptions/p/I.java test/compiler/jsr292/methodHandleExceptions/p/Tdirect.java test/compiler/jsr292/methodHandleExceptions/p/Treflect.java
diffstat 16 files changed, 814 insertions(+), 116 deletions(-) [+]
line wrap: on
line diff
--- a/src/share/vm/classfile/systemDictionary.hpp	Fri Nov 22 13:42:46 2013 -0800
+++ b/src/share/vm/classfile/systemDictionary.hpp	Tue Nov 26 18:16:04 2013 -0500
@@ -165,6 +165,7 @@
                                                                                                                          \
   do_klass(StringBuffer_klass,                          java_lang_StringBuffer,                    Pre                 ) \
   do_klass(StringBuilder_klass,                         java_lang_StringBuilder,                   Pre                 ) \
+  do_klass(misc_Unsafe_klass,                           sun_misc_Unsafe,                           Pre                 ) \
                                                                                                                          \
   /* It's NULL in non-1.4 JDKs. */                                                                                       \
   do_klass(StackTraceElement_klass,                     java_lang_StackTraceElement,               Opt                 ) \
--- a/src/share/vm/classfile/vmSymbols.hpp	Fri Nov 22 13:42:46 2013 -0800
+++ b/src/share/vm/classfile/vmSymbols.hpp	Tue Nov 26 18:16:04 2013 -0500
@@ -331,6 +331,7 @@
   template(findNative_name,                           "findNative")                               \
   template(deadChild_name,                            "deadChild")                                \
   template(addClass_name,                             "addClass")                                 \
+  template(throwIllegalAccessError_name,              "throwIllegalAccessError")                  \
   template(getFromClass_name,                         "getFromClass")                             \
   template(dispatch_name,                             "dispatch")                                 \
   template(getSystemClassLoader_name,                 "getSystemClassLoader")                     \
--- a/src/share/vm/memory/universe.cpp	Fri Nov 22 13:42:46 2013 -0800
+++ b/src/share/vm/memory/universe.cpp	Tue Nov 26 18:16:04 2013 -0500
@@ -120,6 +120,7 @@
 oop Universe::_arithmetic_exception_instance          = NULL;
 oop Universe::_virtual_machine_error_instance         = NULL;
 oop Universe::_vm_exception                           = NULL;
+Method* Universe::_throw_illegal_access_error         = NULL;
 Array<int>* Universe::_the_empty_int_array            = NULL;
 Array<u2>* Universe::_the_empty_short_array           = NULL;
 Array<Klass*>* Universe::_the_empty_klass_array     = NULL;
@@ -1096,6 +1097,18 @@
   Universe::_finalizer_register_cache->init(
     SystemDictionary::Finalizer_klass(), m);
 
+  InstanceKlass::cast(SystemDictionary::misc_Unsafe_klass())->link_class(CHECK_false);
+  m = InstanceKlass::cast(SystemDictionary::misc_Unsafe_klass())->find_method(
+                                  vmSymbols::throwIllegalAccessError_name(),
+                                  vmSymbols::void_method_signature());
+  if (m != NULL && !m->is_static()) {
+    // Note null is okay; this method is used in itables, and if it is null,
+    // then AbstractMethodError is thrown instead.
+    tty->print_cr("Unable to link/verify Unsafe.throwIllegalAccessError method");
+    return false; // initialization failed (cannot throw exception yet)
+  }
+  Universe::_throw_illegal_access_error = m;
+
   // Setup method for registering loaded classes in class loader vector
   InstanceKlass::cast(SystemDictionary::ClassLoader_klass())->link_class(CHECK_false);
   m = InstanceKlass::cast(SystemDictionary::ClassLoader_klass())->find_method(vmSymbols::addClass_name(), vmSymbols::class_void_signature());
--- a/src/share/vm/memory/universe.hpp	Fri Nov 22 13:42:46 2013 -0800
+++ b/src/share/vm/memory/universe.hpp	Tue Nov 26 18:16:04 2013 -0500
@@ -149,6 +149,8 @@
   static LatestMethodCache* _loader_addClass_cache;    // method for registering loaded classes in class loader vector
   static LatestMethodCache* _pd_implies_cache;         // method for checking protection domain attributes
 
+  static Method* _throw_illegal_access_error;
+
   // preallocated error objects (no backtrace)
   static oop          _out_of_memory_error_java_heap;
   static oop          _out_of_memory_error_metaspace;
@@ -305,6 +307,7 @@
   static oop          arithmetic_exception_instance() { return _arithmetic_exception_instance; }
   static oop          virtual_machine_error_instance() { return _virtual_machine_error_instance; }
   static oop          vm_exception()                  { return _vm_exception; }
+  static Method*      throw_illegal_access_error()    { return _throw_illegal_access_error; }
 
   static Array<int>*       the_empty_int_array()    { return _the_empty_int_array; }
   static Array<u2>*        the_empty_short_array()  { return _the_empty_short_array; }
--- a/src/share/vm/oops/klassVtable.cpp	Fri Nov 22 13:42:46 2013 -0800
+++ b/src/share/vm/oops/klassVtable.cpp	Tue Nov 26 18:16:04 2013 -0500
@@ -1076,7 +1076,12 @@
       LinkResolver::lookup_instance_method_in_klasses(target, _klass, m->name(), m->signature(), CHECK);
     }
     if (target == NULL || !target->is_public() || target->is_abstract()) {
-      // Entry do not resolve. Leave it empty
+      // Entry does not resolve. Leave it empty for AbstractMethodError.
+        if (!(target == NULL) && !target->is_public()) {
+          // Stuff an IllegalAccessError throwing method in there instead.
+          itableOffsetEntry::method_entry(_klass(), method_table_offset)[m->itable_index()].
+              initialize(Universe::throw_illegal_access_error());
+        }
     } else {
       // Entry did resolve, check loader constraints before initializing
       // if checkconstraints requested
--- a/test/compiler/jsr292/methodHandleExceptions/ByteClassLoader.java	Fri Nov 22 13:42:46 2013 -0800
+++ b/test/compiler/jsr292/methodHandleExceptions/ByteClassLoader.java	Tue Nov 26 18:16:04 2013 -0500
@@ -1,3 +1,12 @@
+import java.io.BufferedOutputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.util.jar.JarEntry;
+import java.util.jar.JarOutputStream;
+
 /*
  * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
@@ -23,12 +32,63 @@
  */
 
 /**
- * A minimal classloader for loading bytecodes that could not result from
- * properly compiled Java.
+ * A ByteClassLoader is used to define classes from collections of bytes, as
+ * well as loading classes in the usual way. It includes options to write the
+ * classes to files in a jar, or to read the classes from jars in a later or
+ * debugging run.
  *
- * @author dr2chase
+ * If Boolean property byteclassloader.verbose is true, be chatty about jar
+ * file operations.
+ *
  */
-public class ByteClassLoader extends ClassLoader {
+public class ByteClassLoader extends URLClassLoader {
+
+    final static boolean verbose
+            = Boolean.getBoolean("byteclassloader.verbose");
+
+    final boolean read;
+    final JarOutputStream jos;
+    final String jar_name;
+
+    /**
+     * Make a new ByteClassLoader.
+     *
+     * @param jar_name  Basename of jar file to be read/written by this classloader.
+     * @param read      If true, read classes from jar file instead of from parameter.
+     * @param write     If true, write classes to jar files for offline study/use.
+     *
+     * @throws FileNotFoundException
+     * @throws IOException
+     */
+    public ByteClassLoader(String jar_name, boolean read, boolean write)
+            throws FileNotFoundException, IOException {
+        super(read
+                ? new URL[]{new URL("file:" + jar_name + ".jar")}
+                : new URL[0]);
+        this.read = read;
+        this.jar_name = jar_name;
+        this.jos = write
+                ? new JarOutputStream(
+                new BufferedOutputStream(
+                new FileOutputStream(jar_name + ".jar"))) : null;
+        if (read && write) {
+            throw new Error("At most one of read and write may be true.");
+        }
+    }
+
+    private static void writeJarredFile(JarOutputStream jos, String file, String suffix, byte[] bytes) {
+        String fileName = file.replace(".", "/") + "." + suffix;
+        JarEntry ze = new JarEntry(fileName);
+        try {
+            ze.setSize(bytes.length);
+            jos.putNextEntry(ze);
+            jos.write(bytes);
+            jos.closeEntry();
+        } catch (IOException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
     /**
      * (pre)load class name using classData for the definition.
      *
@@ -36,9 +96,36 @@
      * @param classData
      * @return
      */
-    public Class<?> loadBytes(String name, byte[] classData) {
-         Class<?> clazz = defineClass(name, classData, 0, classData.length);
-                     resolveClass(clazz);
-         return clazz;
+    public Class<?> loadBytes(String name, byte[] classData) throws ClassNotFoundException {
+        if (jos != null) {
+            if (verbose) {
+                System.out.println("ByteClassLoader: writing " + name);
+            }
+            writeJarredFile(jos, name, "class", classData);
+        }
+
+        Class<?> clazz = null;
+        if (read) {
+            if (verbose) {
+                System.out.println("ByteClassLoader: reading " + name + " from " + jar_name);
+            }
+            clazz = loadClass(name);
+        } else {
+            clazz = defineClass(name, classData, 0, classData.length);
+            resolveClass(clazz);
+        }
+        return clazz;
+    }
+
+    public void close() {
+        if (jos != null) {
+            try {
+                if (verbose) {
+                    System.out.println("ByteClassLoader: closing " + jar_name);
+                }
+                jos.close();
+            } catch (IOException ex) {
+            }
+        }
     }
 }
--- a/test/compiler/jsr292/methodHandleExceptions/C.java	Fri Nov 22 13:42:46 2013 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,33 +0,0 @@
-/*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * 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.
- *
- */
-
-/**
- * Test class -- implements I, which provides default for m, but this class
- * declares it abstract which (should) hide the interface default, and throw
- * an abstract method error if it is called (calling it requires bytecode hacking
- * or inconsistent compilation).
- */
-public abstract class C implements I {
-       public abstract int m();
-}
--- a/test/compiler/jsr292/methodHandleExceptions/I.java	Fri Nov 22 13:42:46 2013 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,27 +0,0 @@
-/*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * 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.
- *
- */
-
-public interface I {
-    default public int m() { return 1; }
-}
--- a/test/compiler/jsr292/methodHandleExceptions/TestAMEnotNPE.java	Fri Nov 22 13:42:46 2013 -0800
+++ b/test/compiler/jsr292/methodHandleExceptions/TestAMEnotNPE.java	Tue Nov 26 18:16:04 2013 -0500
@@ -21,50 +21,127 @@
  * questions.
  *
  */
-
 import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.List;
 import jdk.internal.org.objectweb.asm.ClassWriter;
 import jdk.internal.org.objectweb.asm.Handle;
 import jdk.internal.org.objectweb.asm.MethodVisitor;
 import jdk.internal.org.objectweb.asm.Opcodes;
+import p.Dok;
 
 /**
- * @test
- * @bug 8025260
- * @summary Ensure that AbstractMethodError is thrown, not NullPointerException, through MethodHandles::jump_from_method_handle code path
+ * @test @bug 8025260 8016839
+ * @summary Ensure that AbstractMethodError and IllegalAccessError are thrown appropriately, not NullPointerException
  *
- * @compile -XDignore.symbol.file ByteClassLoader.java I.java C.java TestAMEnotNPE.java
+ * @compile -XDignore.symbol.file TestAMEnotNPE.java ByteClassLoader.java p/C.java p/Dok.java p/E.java p/F.java p/I.java p/Tdirect.java p/Treflect.java
+ *
  * @run main/othervm TestAMEnotNPE
+ * @run main/othervm -Xint TestAMEnotNPE
+ * @run main/othervm -Xcomp TestAMEnotNPE
  */
-
 public class TestAMEnotNPE implements Opcodes {
 
+    static boolean writeJarFiles = false;
+    static boolean readJarFiles = false;
+
     /**
-     * The bytes for D, a NOT abstract class extending abstract class C
-     * without supplying an implementation for abstract method m.
-     * There is a default method in the interface I, but it should lose to
-     * the abstract class.
+     * Optional command line parameter (any case-insensitive prefix of)
+     * "writejarfiles" or "readjarfiles".
+     *
+     * "Writejarfiles" creates a jar file for each different set of tested classes.
+     * "Readjarfiles" causes the classloader to use the copies of the classes
+     * found in the corresponding jar files.
+     *
+     * Jarfilenames look something like pD_ext_pF (p.D extends p.F)
+     * and qD_m_pp_imp_pI (q.D with package-private m implements p.I)
+     *
+     */
+    public static void main(String args[]) throws Throwable {
+        ArrayList<Throwable> lt = new ArrayList<Throwable>();
 
-     class D extends C {
-        D() { super(); }
-        // does not define m
-     }
+        if (args.length > 0) {
+            String a0 = args[0].toLowerCase();
+            if (a0.length() > 0) {
+                writeJarFiles = ("writejarfiles").startsWith(a0);
+                readJarFiles = ("readjarfiles").startsWith(a0);
+            }
+            if (!(writeJarFiles || readJarFiles)) {
+                throw new Error("Command line parameter (if any) should be prefix of writeJarFiles or readJarFiles");
+            }
+        }
 
+        try {
+            System.out.println("TRYING p.D.m PRIVATE interface-invoked as p.I.m, p.D extends p.F, p.F.m FINAL");
+            tryAndCheckThrown(lt, bytesForDprivateSubWhat("p/F"),
+                    "p.D extends p.F (p.F implements p.I, FINAL public m), private m",
+                    IllegalAccessError.class, "pD_ext_pF");
+            // We'll take either a VerifyError (pre 2013-11-30)
+            // or an IllegalAccessError (post 2013-11-22)
+        } catch (VerifyError ve) {
+            System.out.println("Saw expected VerifyError " + ve);
+        }
+        System.out.println();
+
+        System.out.println("TRYING p.D.m PRIVATE interface-invoked as p.I.m, p.D extends p.E");
+        tryAndCheckThrown(lt, bytesForDprivateSubWhat("p/E"),
+                "p.D extends p.E (p.E implements p.I, public m), private m",
+                IllegalAccessError.class, "pD_ext_pE");
+
+        System.out.println("TRYING p.D.m ABSTRACT interface-invoked as p.I.m");
+        tryAndCheckThrown(lt, bytesForD(),
+                "D extends abstract C, no m",
+                AbstractMethodError.class, "pD_ext_pC");
+
+        System.out.println("TRYING q.D.m PACKAGE interface-invoked as p.I.m");
+        tryAndCheckThrown(lt, "q.D", bytesForDsomeAccess("q/D", 0),
+                "q.D implements p.I, protected m", IllegalAccessError.class,
+                "qD_m_pp_imp_pI");
+
+        // Note jar file name is used in the plural-arg case.
+        System.out.println("TRYING p.D.m PRIVATE interface-invoked as p.I.m");
+        tryAndCheckThrown(lt, bytesForDsomeAccess("p/D", ACC_PRIVATE),
+                "p.D implements p.I, private m",
+                IllegalAccessError.class, "pD_m_pri_imp_pI");
+
+        // Plural-arg test.
+        System.out.println("TRYING p.D.m PRIVATE MANY ARG interface-invoked as p.I.m");
+        tryAndCheckThrownMany(lt, bytesForDsomeAccess("p/D", ACC_PRIVATE),
+                "p.D implements p.I, private m", IllegalAccessError.class);
+
+        if (lt.size() > 0) {
+            System.out.flush();
+            Thread.sleep(250); // This de-interleaves output and error in Netbeans, sigh.
+            for (Throwable th : lt)
+              System.err.println(th);
+            throw new Error("Test failed, there were " + lt.size() + " failures listed above");
+        } else {
+            System.out.println("ALL PASS, HOORAY!");
+        }
+    }
+
+    /**
+     * The bytes for D, a NOT abstract class extending abstract class C without
+     * supplying an implementation for abstract method m. There is a default
+     * method in the interface I, but it should lose to the abstract class.
+     *
      * @return
      * @throws Exception
      */
     public static byte[] bytesForD() throws Exception {
 
-        ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES|ClassWriter.COMPUTE_MAXS);
+        ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES
+                | ClassWriter.COMPUTE_MAXS);
         MethodVisitor mv;
 
-        cw.visit(V1_8, ACC_PUBLIC + ACC_SUPER, "D", null, "C", null);
+        cw.visit(V1_8, ACC_PUBLIC + ACC_SUPER, "p/D", null, "p/C", null);
 
         {
             mv = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null);
             mv.visitCode();
             mv.visitVarInsn(ALOAD, 0);
-            mv.visitMethodInsn(INVOKESPECIAL, "C", "<init>", "()V");
+            mv.visitMethodInsn(INVOKESPECIAL, "p/C", "<init>", "()V");
             mv.visitInsn(RETURN);
             mv.visitMaxs(0, 0);
             mv.visitEnd();
@@ -74,70 +151,346 @@
         return cw.toByteArray();
     }
 
+    /**
+     * The bytes for D, implements I, does not extend C, declares m()I with
+     * access method_acc.
+     *
+     * @param d_name Name of class defined
+     * @param method_acc Accessibility of that class's method m.
+     * @return
+     * @throws Exception
+     */
+    public static byte[] bytesForDsomeAccess(String d_name, int method_acc) throws Exception {
+        return bytesForSomeDsubSomethingSomeAccess(d_name, "java/lang/Object", method_acc);
+    }
 
     /**
-     * The bytecodes for an invokeExact of a particular methodHandle, I.m, invoked on a D
+     * The bytes for D implements I, extends some class, declares m()I as
+     * private.
+     *
+     * Invokeinterface of I.m applied to this D should throw IllegalAccessError
+     *
+     * @param sub_what The name of the class that D will extend.
+     * @return
+     * @throws Exception
+     */
+    public static byte[] bytesForDprivateSubWhat(String sub_what) throws Exception {
+        return bytesForSomeDsubSomethingSomeAccess("p/D", sub_what, ACC_PRIVATE);
+    }
 
-        class T {
-           T() { super(); } // boring constructor
-           int test() {
-              MethodHandle mh = `I.m():int`;
-              D d = new D();
-              return mh.invokeExact(d); // Should explode here, AbstractMethodError
-           }
+    /**
+     * Returns the bytes for a class with name d_name (presumably "D" in some
+     * package), extending some class with name sub_what, implementing p.I,
+     * and defining two methods m() and m(11args) with access method_acc.
+     *
+     * @param d_name      Name of class that is defined
+     * @param sub_what    Name of class that it extends
+     * @param method_acc  Accessibility of method(s) m in defined class.
+     * @return
+     * @throws Exception
+     */
+    public static byte[] bytesForSomeDsubSomethingSomeAccess
+            (String d_name, String sub_what, int method_acc)
+            throws Exception {
+
+        ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES
+                | ClassWriter.COMPUTE_MAXS);
+        MethodVisitor mv;
+        String[] interfaces = {"p/I"};
+
+        cw.visit(V1_8, ACC_PUBLIC + ACC_SUPER, d_name, null, sub_what, interfaces);
+        {
+            mv = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null);
+            mv.visitCode();
+            mv.visitVarInsn(ALOAD, 0);
+            mv.visitMethodInsn(INVOKESPECIAL, sub_what, "<init>", "()V");
+            mv.visitInsn(RETURN);
+            mv.visitMaxs(0, 0);
+            mv.visitEnd();
         }
+        // int m() {return 3;}
+        {
+            mv = cw.visitMethod(method_acc, "m", "()I", null, null);
+            mv.visitCode();
+            mv.visitLdcInsn(new Integer(3));
+            mv.visitInsn(IRETURN);
+            mv.visitMaxs(0, 0);
+            mv.visitEnd();
+        }
+        // int m(11args) {return 3;}
+        {
+            mv = cw.visitMethod(method_acc, "m", "(BCSIJ"
+                    + "Ljava/lang/Object;"
+                    + "Ljava/lang/Object;"
+                    + "Ljava/lang/Object;"
+                    + "Ljava/lang/Object;"
+                    + "Ljava/lang/Object;"
+                    + "Ljava/lang/Object;"
+                    + ")I", null, null);
+            mv.visitCode();
+            mv.visitLdcInsn(new Integer(3));
+            mv.visitInsn(IRETURN);
+            mv.visitMaxs(0, 0);
+            mv.visitEnd();
+        }
+        cw.visitEnd();
+        return cw.toByteArray();
+    }
 
+    /**
+     * The bytecodes for a class p/T defining a methods test() and test(11args)
+     * that contain an invokeExact of a particular methodHandle, I.m.
+     *
+     * Test will be passed values that may imperfectly implement I,
+     * and thus may in turn throw exceptions.
+     *
      * @return
      * @throws Exception
      */
     public static byte[] bytesForT() throws Exception {
 
-        ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES|ClassWriter.COMPUTE_MAXS);
+        ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES
+                | ClassWriter.COMPUTE_MAXS);
         MethodVisitor mv;
 
-        cw.visit(V1_8, ACC_PUBLIC + ACC_SUPER, "T", null, "java/lang/Object", null);
+        cw.visit(V1_8, ACC_PUBLIC + ACC_SUPER, "p/T", null, "java/lang/Object", null);
         {
             mv = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null);
             mv.visitCode();
             mv.visitVarInsn(ALOAD, 0);
             mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V");
             mv.visitInsn(RETURN);
-            mv.visitMaxs(0,0);
+            mv.visitMaxs(0, 0);
             mv.visitEnd();
         }
+        // static int test(I)
         {
-            mv = cw.visitMethod(ACC_PUBLIC + ACC_STATIC, "test", "()I", null, null);
+            mv = cw.visitMethod(ACC_PUBLIC + ACC_STATIC, "test", "(Lp/I;)I", null, null);
             mv.visitCode();
-            mv.visitLdcInsn(new Handle(Opcodes.H_INVOKEINTERFACE, "I", "m", "()I"));
-            mv.visitTypeInsn(NEW, "D");
-            mv.visitInsn(DUP);
-            mv.visitMethodInsn(INVOKESPECIAL, "D", "<init>", "()V");
-            mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/invoke/MethodHandle", "invokeExact", "(LI;)I");
+            mv.visitLdcInsn(new Handle(Opcodes.H_INVOKEINTERFACE, "p/I", "m", "()I"));
+            mv.visitVarInsn(ALOAD, 0);
+            mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/invoke/MethodHandle",
+                    "invokeExact", "(Lp/I;)I");
             mv.visitInsn(IRETURN);
-            mv.visitMaxs(0,0);
+            mv.visitMaxs(0, 0);
+            mv.visitEnd();
+        }
+        // static int test(I,11args)
+        {
+            mv = cw.visitMethod(ACC_PUBLIC + ACC_STATIC, "test", "(Lp/I;BCSIJLjava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)I", null, null);
+            mv.visitCode();
+            mv.visitLdcInsn(new Handle(Opcodes.H_INVOKEINTERFACE, "p/I", "m", "(BCSIJLjava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)I"));
+            mv.visitVarInsn(ALOAD, 0);
+            mv.visitVarInsn(ILOAD, 1);
+            mv.visitVarInsn(ILOAD, 2);
+            mv.visitVarInsn(ILOAD, 3);
+            mv.visitVarInsn(ILOAD, 4);
+            mv.visitVarInsn(LLOAD, 5);
+            mv.visitVarInsn(ALOAD, 7);
+            mv.visitVarInsn(ALOAD, 8);
+            mv.visitVarInsn(ALOAD, 9);
+            mv.visitVarInsn(ALOAD, 10);
+            mv.visitVarInsn(ALOAD, 11);
+            mv.visitVarInsn(ALOAD, 12);
+            mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/invoke/MethodHandle",
+                    "invokeExact", "(Lp/I;BCSIJLjava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)I");
+            mv.visitInsn(IRETURN);
+            mv.visitMaxs(0, 0);
             mv.visitEnd();
         }
         cw.visitEnd();
         return cw.toByteArray();
     }
 
-    public static void main(String args[] ) throws Throwable {
-        ByteClassLoader bcl = new ByteClassLoader();
-        Class<?> d = bcl.loadBytes("D", bytesForD());
-        Class<?> t = bcl.loadBytes("T", bytesForT());
+    private static void tryAndCheckThrown(
+            List<Throwable> lt, byte[] dBytes, String what, Class<?> expected, String jar_name)
+            throws Throwable {
+        tryAndCheckThrown(lt, "p.D", dBytes, what, expected, jar_name);
+    }
+
+    private static void tryAndCheckThrown(List<Throwable> lt, String d_name, byte[] dBytes, String what, Class<?> expected, String jar_name)
+            throws Throwable {
+
+        System.out.println("Methodhandle invokeExact I.m() for instance of " + what);
+        ByteClassLoader bcl1 = new ByteClassLoader(jar_name, readJarFiles, writeJarFiles);
         try {
-          Object result = t.getMethod("test").invoke(null);
-          System.out.println("Expected AbstractMethodError wrapped in InvocationTargetException, saw no exception");
-          throw new Error("Missing expected exception");
+            Class<?> d1 = bcl1.loadBytes(d_name, dBytes);
+            Class<?> t1 = bcl1.loadBytes("p.T", bytesForT());
+            invokeTest(t1, d1, expected, lt);
+        } finally {
+            // Not necessary for others -- all class files are written in this call.
+            // (unless the VM crashes first).
+            bcl1.close();
+        }
+
+        System.out.println("Reflection invoke I.m() for instance of " + what);
+        ByteClassLoader bcl3 = new ByteClassLoader(jar_name, readJarFiles, false);
+        Class<?> d3 = bcl3.loadBytes(d_name, dBytes);
+        Class<?> t3 = bcl3.loadClass("p.Treflect");
+        invokeTest(t3, d3, expected, lt);
+
+        System.out.println("Bytecode invokeInterface I.m() for instance of " + what);
+        ByteClassLoader bcl2 = new ByteClassLoader(jar_name, readJarFiles, false);
+        Class<?> d2 = bcl2.loadBytes(d_name, dBytes);
+        Class<?> t2 = bcl2.loadClass("p.Tdirect");
+        badGoodBadGood(t2, d2, expected, lt);
+    }
+
+    private static void invokeTest(Class<?> t, Class<?> d, Class<?> expected, List<Throwable> lt)
+            throws Throwable {
+        try {
+            Method m = t.getMethod("test", p.I.class);
+            Object o = d.newInstance();
+            Object result = m.invoke(null, o);
+            if (expected != null) {
+                System.out.println("FAIL, Expected " + expected.getName()
+                        + " wrapped in InvocationTargetException, but nothing was thrown");
+                lt.add(new Error("Exception " + expected.getName() + " was not thrown"));
+            } else {
+                System.out.println("PASS, saw expected return.");
+            }
         } catch (InvocationTargetException e) {
             Throwable th = e.getCause();
-            if (th instanceof AbstractMethodError) {
-                th.printStackTrace(System.out);
-                System.out.println("PASS, saw expected exception (AbstractMethodError, wrapped in InvocationTargetException).");
+            th.printStackTrace(System.out);
+            if (expected != null) {
+                if (expected.isInstance(th)) {
+                    System.out.println("PASS, saw expected exception (" + expected.getName() + ").");
+                } else {
+                    System.out.println("FAIL, Expected " + expected.getName()
+                            + " wrapped in InvocationTargetException, saw " + th);
+                    lt.add(th);
+                }
             } else {
-                System.out.println("Expected AbstractMethodError wrapped in InvocationTargetException, saw " + th);
-                throw th;
+                System.out.println("FAIL, expected no exception, saw " + th);
+                lt.add(th);
             }
         }
+        System.out.println();
+    }
+
+    /* Many-arg versions of above */
+    private static void tryAndCheckThrownMany(List<Throwable> lt, byte[] dBytes, String what, Class<?> expected)
+            throws Throwable {
+
+        System.out.println("Methodhandle invokeExact I.m(11params) for instance of " + what);
+        ByteClassLoader bcl1 = new ByteClassLoader("p.D", readJarFiles, false);
+        try {
+            Class<?> d1 = bcl1.loadBytes("p.D", dBytes);
+            Class<?> t1 = bcl1.loadBytes("p.T", bytesForT());
+            invokeTestMany(t1, d1, expected, lt);
+        } finally {
+            bcl1.close(); // Not necessary for others -- all class files are written in this call.
+        }
+
+        {
+            System.out.println("Bytecode invokeInterface I.m(11params) for instance of " + what);
+            ByteClassLoader bcl2 = new ByteClassLoader("pD_m_pri_imp_pI", readJarFiles, false);
+            Class<?> d2 = bcl2.loadBytes("p.D", dBytes);
+            Class<?> t2 = bcl2.loadClass("p.Tdirect");
+            badGoodBadGoodMany(t2, d2, expected, lt);
+
+        }
+        {
+            System.out.println("Reflection invokeInterface I.m(11params) for instance of " + what);
+            ByteClassLoader bcl2 = new ByteClassLoader("pD_m_pri_imp_pI", readJarFiles, false);
+            Class<?> d2 = bcl2.loadBytes("p.D", dBytes);
+            Class<?> t2 = bcl2.loadClass("p.Treflect");
+            invokeTestMany(t2, d2, expected, lt);
+        }
+    }
+
+    private static void invokeTestMany(Class<?> t, Class<?> d, Class<?> expected, List<Throwable> lt)
+            throws Throwable {
+        try {
+            Method m = t.getMethod("test", p.I.class,
+                    Byte.TYPE, Character.TYPE, Short.TYPE, Integer.TYPE, Long.TYPE,
+                    Object.class, Object.class, Object.class,
+                    Object.class, Object.class, Object.class);
+            Object o = d.newInstance();
+            Byte b = 1;
+            Character c = 2;
+            Short s = 3;
+            Integer i = 4;
+            Long j = 5L;
+            Object o1 = b;
+            Object o2 = c;
+            Object o3 = s;
+            Object o4 = i;
+            Object o5 = j;
+            Object o6 = "6";
+
+            Object result = m.invoke(null, o, b, c, s, i, j,
+                    o1, o2, o3, o4, o5, o6);
+            if (expected != null) {
+                System.out.println("FAIL, Expected " + expected.getName()
+                        + " wrapped in InvocationTargetException, but nothing was thrown");
+                lt.add(new Error("Exception " + expected.getName()
+                        + " was not thrown"));
+            } else {
+                System.out.println("PASS, saw expected return.");
+            }
+        } catch (InvocationTargetException e) {
+            Throwable th = e.getCause();
+            th.printStackTrace(System.out);
+            if (expected != null) {
+                if (expected.isInstance(th)) {
+                    System.out.println("PASS, saw expected exception ("
+                            + expected.getName() + ").");
+                } else {
+                    System.out.println("FAIL, Expected " + expected.getName()
+                            + " wrapped in InvocationTargetException, saw " + th);
+                    lt.add(th);
+                }
+            } else {
+                System.out.println("FAIL, expected no exception, saw " + th);
+                lt.add(th);
+            }
+        }
+        System.out.println();
+    }
+
+    /**
+     * This tests a peculiar idiom for tickling the bug on older VMs that lack
+     * methodhandles.  The bug (if not fixed) acts in the following way:
+     *
+     *  When a broken receiver is passed to the first execution of an invokeinterface
+     * bytecode, the illegal access is detected before the effects of resolution are
+     * cached for later use, and so repeated calls with a broken receiver will always
+     * throw the correct error.
+     *
+     * If, however, a good receiver is passed to the invokeinterface, the effects of
+     * resolution will be successfully cached.  A subsequent execution with a broken
+     * receiver will reuse the cached information, skip the detailed resolution work,
+     * and instead encounter a null pointer.  By convention, that is the encoding for a
+     * missing abstract method, and an AbstractMethodError is thrown -- not the expected
+     * IllegalAccessError.
+     *
+     * @param t2 Test invocation class
+     * @param d2 Test receiver class
+     * @param expected expected exception type
+     * @param lt list of unexpected throwables seen
+     */
+    private static void badGoodBadGood(Class<?> t2, Class<?> d2, Class<?> expected, List<Throwable> lt)
+            throws Throwable {
+        System.out.println("  Error input 1st time");
+        invokeTest(t2, d2, expected, lt);
+        System.out.println("  Good input (instance of Dok)");
+        invokeTest(t2, Dok.class, null, lt);
+        System.out.println("  Error input 2nd time");
+        invokeTest(t2, d2, expected, lt);
+        System.out.println("  Good input (instance of Dok)");
+        invokeTest(t2, Dok.class, null, lt);
+    }
+
+    private static void badGoodBadGoodMany(Class<?> t2, Class<?> d2, Class<?> expected, List<Throwable> lt)
+            throws Throwable {
+        System.out.println("  Error input 1st time");
+        invokeTestMany(t2, d2, expected, lt);
+        System.out.println("  Good input (instance of Dok)");
+        invokeTestMany(t2, Dok.class, null, lt);
+        System.out.println("  Error input 2nd time");
+        invokeTestMany(t2, d2, expected, lt);
+        System.out.println("  Good input (instance of Dok)");
+        invokeTestMany(t2, Dok.class, null, lt);
     }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/compiler/jsr292/methodHandleExceptions/p/C.java	Tue Nov 26 18:16:04 2013 -0500
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * 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 p;
+
+/**
+ * Test class -- implements I, which provides default for m, but this class
+ * declares it abstract which (should) hide the interface default, and throw
+ * an abstract method error if called.
+ *
+ */
+public abstract class C implements p.I {
+       public abstract int m();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/compiler/jsr292/methodHandleExceptions/p/Dok.java	Tue Nov 26 18:16:04 2013 -0500
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * 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 p;
+
+/**
+ * Test class -- implements I, extends E, both define m, so all should be well.
+ */
+public class Dok extends p.E {
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/compiler/jsr292/methodHandleExceptions/p/E.java	Tue Nov 26 18:16:04 2013 -0500
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * 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 p;
+
+/**
+ * Test class -- implements I, which provides default for m, but this class
+ * redeclares it so that all its non-overriding descendants should call its
+ * method instead (with no error, assuming no descendant monkey business, which
+ * of course is NOT usually the case in this test).
+ *
+ */
+public abstract class E implements p.I {
+       public int m() {
+           return 2;
+       }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/compiler/jsr292/methodHandleExceptions/p/F.java	Tue Nov 26 18:16:04 2013 -0500
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * 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 p;
+
+/**
+ * Test class -- implements I, which provides default for m, but this class
+ * redeclares it so that all its non-overriding descendants should call its
+ * method instead (with no error, assuming no descendant monkey business, which
+ * of course is NOT usually the case in this test).
+ *
+ * Note that m is final -- one form of monkey business is attempting to redefine
+ * m.
+ *
+ */
+public abstract class F implements p.I {
+       final public int m() {
+           return 2;
+       }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/compiler/jsr292/methodHandleExceptions/p/I.java	Tue Nov 26 18:16:04 2013 -0500
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * 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 p;
+
+/**
+ * Test interface I, provides default implementations for m() and m(11args).
+ */
+
+public interface I {
+    default public int m() { return 1; }
+    default public int m(byte b, char c, short s, int i, long l,
+           Object o1, Object o2, Object o3, Object o4, Object o5, Object o6) {
+        return 2;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/compiler/jsr292/methodHandleExceptions/p/Tdirect.java	Tue Nov 26 18:16:04 2013 -0500
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * 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 p;
+
+/**
+ * Invokes I.m directly using invokeInterface bytecodes.
+ */
+public class Tdirect {
+     public static int test(p.I i) {
+         int accum = 0;
+         for (int j = 0; j < 100000; j++) {
+             accum += i.m();
+         }
+        return accum;
+    }
+
+     public static int test(p.I ii, byte b, char c, short s, int i, long l,
+             Object o1, Object o2, Object o3, Object o4, Object o5, Object o6) {
+         int accum = 0;
+         for (int j = 0; j < 100000; j++) {
+           accum += ii.m(b,c,s,i,l,o1,o2,o3,o4,o5,o6);
+         }
+         return accum;
+     }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/compiler/jsr292/methodHandleExceptions/p/Treflect.java	Tue Nov 26 18:16:04 2013 -0500
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * 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 p;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+
+/**
+ * Invokes I.m using reflection.
+ */
+public class Treflect {
+
+    public static int test(p.I ii) throws Throwable {
+        int accum = 0;
+        Method m = p.I.class.getMethod("m");
+        try {
+            for (int j = 0; j < 100000; j++) {
+                Object o = m.invoke(ii);
+                accum += ((Integer) o).intValue();
+            }
+        } catch (InvocationTargetException ite) {
+            throw ite.getCause();
+        }
+        return accum;
+    }
+
+    public static int test(p.I ii, byte b, char c, short s, int i, long l,
+            Object o1, Object o2, Object o3, Object o4, Object o5, Object o6)
+            throws Throwable {
+        Method m = p.I.class.getMethod("m", Byte.TYPE, Character.TYPE,
+                Short.TYPE, Integer.TYPE, Long.TYPE,
+                Object.class, Object.class, Object.class,
+                Object.class, Object.class, Object.class);
+        int accum = 0;
+        try {
+            for (int j = 0; j < 100000; j++) {
+                Object o = m.invoke(ii, b, c, s, i, l, o1, o2, o3, o4, o5, o6);
+                accum += ((Integer) o).intValue();
+            }
+        } catch (InvocationTargetException ite) {
+            throw ite.getCause();
+        }
+        return accum;
+    }
+}