hotspot/test/compiler/jsr292/methodHandleExceptions/TestAMEnotNPE.java
changeset 21770 e8932d2fda2c
parent 20298 861da81238ee
child 29678 dd2f3932c21e
equal deleted inserted replaced
21764:ba63dd5d7b20 21770:e8932d2fda2c
    19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    20  * or visit www.oracle.com if you need additional information or have any
    20  * or visit www.oracle.com if you need additional information or have any
    21  * questions.
    21  * questions.
    22  *
    22  *
    23  */
    23  */
    24 
       
    25 import java.lang.reflect.InvocationTargetException;
    24 import java.lang.reflect.InvocationTargetException;
       
    25 import java.lang.reflect.Method;
       
    26 import java.util.ArrayList;
       
    27 import java.util.List;
    26 import jdk.internal.org.objectweb.asm.ClassWriter;
    28 import jdk.internal.org.objectweb.asm.ClassWriter;
    27 import jdk.internal.org.objectweb.asm.Handle;
    29 import jdk.internal.org.objectweb.asm.Handle;
    28 import jdk.internal.org.objectweb.asm.MethodVisitor;
    30 import jdk.internal.org.objectweb.asm.MethodVisitor;
    29 import jdk.internal.org.objectweb.asm.Opcodes;
    31 import jdk.internal.org.objectweb.asm.Opcodes;
       
    32 import p.Dok;
    30 
    33 
    31 /**
    34 /**
    32  * @test
    35  * @test @bug 8025260 8016839
    33  * @bug 8025260
    36  * @summary Ensure that AbstractMethodError and IllegalAccessError are thrown appropriately, not NullPointerException
    34  * @summary Ensure that AbstractMethodError is thrown, not NullPointerException, through MethodHandles::jump_from_method_handle code path
    37  *
    35  *
    38  * @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
    36  * @compile -XDignore.symbol.file ByteClassLoader.java I.java C.java TestAMEnotNPE.java
    39  *
    37  * @run main/othervm TestAMEnotNPE
    40  * @run main/othervm TestAMEnotNPE
       
    41  * @run main/othervm -Xint TestAMEnotNPE
       
    42  * @run main/othervm -Xcomp TestAMEnotNPE
    38  */
    43  */
    39 
       
    40 public class TestAMEnotNPE implements Opcodes {
    44 public class TestAMEnotNPE implements Opcodes {
    41 
    45 
    42     /**
    46     static boolean writeJarFiles = false;
    43      * The bytes for D, a NOT abstract class extending abstract class C
    47     static boolean readJarFiles = false;
    44      * without supplying an implementation for abstract method m.
    48 
    45      * There is a default method in the interface I, but it should lose to
    49     /**
    46      * the abstract class.
    50      * Optional command line parameter (any case-insensitive prefix of)
    47 
    51      * "writejarfiles" or "readjarfiles".
    48      class D extends C {
    52      *
    49         D() { super(); }
    53      * "Writejarfiles" creates a jar file for each different set of tested classes.
    50         // does not define m
    54      * "Readjarfiles" causes the classloader to use the copies of the classes
    51      }
    55      * found in the corresponding jar files.
    52 
    56      *
       
    57      * Jarfilenames look something like pD_ext_pF (p.D extends p.F)
       
    58      * and qD_m_pp_imp_pI (q.D with package-private m implements p.I)
       
    59      *
       
    60      */
       
    61     public static void main(String args[]) throws Throwable {
       
    62         ArrayList<Throwable> lt = new ArrayList<Throwable>();
       
    63 
       
    64         if (args.length > 0) {
       
    65             String a0 = args[0].toLowerCase();
       
    66             if (a0.length() > 0) {
       
    67                 writeJarFiles = ("writejarfiles").startsWith(a0);
       
    68                 readJarFiles = ("readjarfiles").startsWith(a0);
       
    69             }
       
    70             if (!(writeJarFiles || readJarFiles)) {
       
    71                 throw new Error("Command line parameter (if any) should be prefix of writeJarFiles or readJarFiles");
       
    72             }
       
    73         }
       
    74 
       
    75         try {
       
    76             System.out.println("TRYING p.D.m PRIVATE interface-invoked as p.I.m, p.D extends p.F, p.F.m FINAL");
       
    77             tryAndCheckThrown(lt, bytesForDprivateSubWhat("p/F"),
       
    78                     "p.D extends p.F (p.F implements p.I, FINAL public m), private m",
       
    79                     IllegalAccessError.class, "pD_ext_pF");
       
    80             // We'll take either a VerifyError (pre 2013-11-30)
       
    81             // or an IllegalAccessError (post 2013-11-22)
       
    82         } catch (VerifyError ve) {
       
    83             System.out.println("Saw expected VerifyError " + ve);
       
    84         }
       
    85         System.out.println();
       
    86 
       
    87         System.out.println("TRYING p.D.m PRIVATE interface-invoked as p.I.m, p.D extends p.E");
       
    88         tryAndCheckThrown(lt, bytesForDprivateSubWhat("p/E"),
       
    89                 "p.D extends p.E (p.E implements p.I, public m), private m",
       
    90                 IllegalAccessError.class, "pD_ext_pE");
       
    91 
       
    92         System.out.println("TRYING p.D.m ABSTRACT interface-invoked as p.I.m");
       
    93         tryAndCheckThrown(lt, bytesForD(),
       
    94                 "D extends abstract C, no m",
       
    95                 AbstractMethodError.class, "pD_ext_pC");
       
    96 
       
    97         System.out.println("TRYING q.D.m PACKAGE interface-invoked as p.I.m");
       
    98         tryAndCheckThrown(lt, "q.D", bytesForDsomeAccess("q/D", 0),
       
    99                 "q.D implements p.I, protected m", IllegalAccessError.class,
       
   100                 "qD_m_pp_imp_pI");
       
   101 
       
   102         // Note jar file name is used in the plural-arg case.
       
   103         System.out.println("TRYING p.D.m PRIVATE interface-invoked as p.I.m");
       
   104         tryAndCheckThrown(lt, bytesForDsomeAccess("p/D", ACC_PRIVATE),
       
   105                 "p.D implements p.I, private m",
       
   106                 IllegalAccessError.class, "pD_m_pri_imp_pI");
       
   107 
       
   108         // Plural-arg test.
       
   109         System.out.println("TRYING p.D.m PRIVATE MANY ARG interface-invoked as p.I.m");
       
   110         tryAndCheckThrownMany(lt, bytesForDsomeAccess("p/D", ACC_PRIVATE),
       
   111                 "p.D implements p.I, private m", IllegalAccessError.class);
       
   112 
       
   113         if (lt.size() > 0) {
       
   114             System.out.flush();
       
   115             Thread.sleep(250); // This de-interleaves output and error in Netbeans, sigh.
       
   116             for (Throwable th : lt)
       
   117               System.err.println(th);
       
   118             throw new Error("Test failed, there were " + lt.size() + " failures listed above");
       
   119         } else {
       
   120             System.out.println("ALL PASS, HOORAY!");
       
   121         }
       
   122     }
       
   123 
       
   124     /**
       
   125      * The bytes for D, a NOT abstract class extending abstract class C without
       
   126      * supplying an implementation for abstract method m. There is a default
       
   127      * method in the interface I, but it should lose to the abstract class.
       
   128      *
    53      * @return
   129      * @return
    54      * @throws Exception
   130      * @throws Exception
    55      */
   131      */
    56     public static byte[] bytesForD() throws Exception {
   132     public static byte[] bytesForD() throws Exception {
    57 
   133 
    58         ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES|ClassWriter.COMPUTE_MAXS);
   134         ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES
       
   135                 | ClassWriter.COMPUTE_MAXS);
    59         MethodVisitor mv;
   136         MethodVisitor mv;
    60 
   137 
    61         cw.visit(V1_8, ACC_PUBLIC + ACC_SUPER, "D", null, "C", null);
   138         cw.visit(V1_8, ACC_PUBLIC + ACC_SUPER, "p/D", null, "p/C", null);
    62 
   139 
    63         {
   140         {
    64             mv = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null);
   141             mv = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null);
    65             mv.visitCode();
   142             mv.visitCode();
    66             mv.visitVarInsn(ALOAD, 0);
   143             mv.visitVarInsn(ALOAD, 0);
    67             mv.visitMethodInsn(INVOKESPECIAL, "C", "<init>", "()V");
   144             mv.visitMethodInsn(INVOKESPECIAL, "p/C", "<init>", "()V");
    68             mv.visitInsn(RETURN);
   145             mv.visitInsn(RETURN);
    69             mv.visitMaxs(0, 0);
   146             mv.visitMaxs(0, 0);
    70             mv.visitEnd();
   147             mv.visitEnd();
    71         }
   148         }
    72         cw.visitEnd();
   149         cw.visitEnd();
    73 
   150 
    74         return cw.toByteArray();
   151         return cw.toByteArray();
    75     }
   152     }
    76 
   153 
    77 
   154     /**
    78     /**
   155      * The bytes for D, implements I, does not extend C, declares m()I with
    79      * The bytecodes for an invokeExact of a particular methodHandle, I.m, invoked on a D
   156      * access method_acc.
    80 
   157      *
    81         class T {
   158      * @param d_name Name of class defined
    82            T() { super(); } // boring constructor
   159      * @param method_acc Accessibility of that class's method m.
    83            int test() {
       
    84               MethodHandle mh = `I.m():int`;
       
    85               D d = new D();
       
    86               return mh.invokeExact(d); // Should explode here, AbstractMethodError
       
    87            }
       
    88         }
       
    89 
       
    90      * @return
   160      * @return
    91      * @throws Exception
   161      * @throws Exception
    92      */
   162      */
       
   163     public static byte[] bytesForDsomeAccess(String d_name, int method_acc) throws Exception {
       
   164         return bytesForSomeDsubSomethingSomeAccess(d_name, "java/lang/Object", method_acc);
       
   165     }
       
   166 
       
   167     /**
       
   168      * The bytes for D implements I, extends some class, declares m()I as
       
   169      * private.
       
   170      *
       
   171      * Invokeinterface of I.m applied to this D should throw IllegalAccessError
       
   172      *
       
   173      * @param sub_what The name of the class that D will extend.
       
   174      * @return
       
   175      * @throws Exception
       
   176      */
       
   177     public static byte[] bytesForDprivateSubWhat(String sub_what) throws Exception {
       
   178         return bytesForSomeDsubSomethingSomeAccess("p/D", sub_what, ACC_PRIVATE);
       
   179     }
       
   180 
       
   181     /**
       
   182      * Returns the bytes for a class with name d_name (presumably "D" in some
       
   183      * package), extending some class with name sub_what, implementing p.I,
       
   184      * and defining two methods m() and m(11args) with access method_acc.
       
   185      *
       
   186      * @param d_name      Name of class that is defined
       
   187      * @param sub_what    Name of class that it extends
       
   188      * @param method_acc  Accessibility of method(s) m in defined class.
       
   189      * @return
       
   190      * @throws Exception
       
   191      */
       
   192     public static byte[] bytesForSomeDsubSomethingSomeAccess
       
   193             (String d_name, String sub_what, int method_acc)
       
   194             throws Exception {
       
   195 
       
   196         ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES
       
   197                 | ClassWriter.COMPUTE_MAXS);
       
   198         MethodVisitor mv;
       
   199         String[] interfaces = {"p/I"};
       
   200 
       
   201         cw.visit(V1_8, ACC_PUBLIC + ACC_SUPER, d_name, null, sub_what, interfaces);
       
   202         {
       
   203             mv = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null);
       
   204             mv.visitCode();
       
   205             mv.visitVarInsn(ALOAD, 0);
       
   206             mv.visitMethodInsn(INVOKESPECIAL, sub_what, "<init>", "()V");
       
   207             mv.visitInsn(RETURN);
       
   208             mv.visitMaxs(0, 0);
       
   209             mv.visitEnd();
       
   210         }
       
   211         // int m() {return 3;}
       
   212         {
       
   213             mv = cw.visitMethod(method_acc, "m", "()I", null, null);
       
   214             mv.visitCode();
       
   215             mv.visitLdcInsn(new Integer(3));
       
   216             mv.visitInsn(IRETURN);
       
   217             mv.visitMaxs(0, 0);
       
   218             mv.visitEnd();
       
   219         }
       
   220         // int m(11args) {return 3;}
       
   221         {
       
   222             mv = cw.visitMethod(method_acc, "m", "(BCSIJ"
       
   223                     + "Ljava/lang/Object;"
       
   224                     + "Ljava/lang/Object;"
       
   225                     + "Ljava/lang/Object;"
       
   226                     + "Ljava/lang/Object;"
       
   227                     + "Ljava/lang/Object;"
       
   228                     + "Ljava/lang/Object;"
       
   229                     + ")I", null, null);
       
   230             mv.visitCode();
       
   231             mv.visitLdcInsn(new Integer(3));
       
   232             mv.visitInsn(IRETURN);
       
   233             mv.visitMaxs(0, 0);
       
   234             mv.visitEnd();
       
   235         }
       
   236         cw.visitEnd();
       
   237         return cw.toByteArray();
       
   238     }
       
   239 
       
   240     /**
       
   241      * The bytecodes for a class p/T defining a methods test() and test(11args)
       
   242      * that contain an invokeExact of a particular methodHandle, I.m.
       
   243      *
       
   244      * Test will be passed values that may imperfectly implement I,
       
   245      * and thus may in turn throw exceptions.
       
   246      *
       
   247      * @return
       
   248      * @throws Exception
       
   249      */
    93     public static byte[] bytesForT() throws Exception {
   250     public static byte[] bytesForT() throws Exception {
    94 
   251 
    95         ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES|ClassWriter.COMPUTE_MAXS);
   252         ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES
       
   253                 | ClassWriter.COMPUTE_MAXS);
    96         MethodVisitor mv;
   254         MethodVisitor mv;
    97 
   255 
    98         cw.visit(V1_8, ACC_PUBLIC + ACC_SUPER, "T", null, "java/lang/Object", null);
   256         cw.visit(V1_8, ACC_PUBLIC + ACC_SUPER, "p/T", null, "java/lang/Object", null);
    99         {
   257         {
   100             mv = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null);
   258             mv = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null);
   101             mv.visitCode();
   259             mv.visitCode();
   102             mv.visitVarInsn(ALOAD, 0);
   260             mv.visitVarInsn(ALOAD, 0);
   103             mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V");
   261             mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V");
   104             mv.visitInsn(RETURN);
   262             mv.visitInsn(RETURN);
   105             mv.visitMaxs(0,0);
   263             mv.visitMaxs(0, 0);
   106             mv.visitEnd();
   264             mv.visitEnd();
   107         }
   265         }
   108         {
   266         // static int test(I)
   109             mv = cw.visitMethod(ACC_PUBLIC + ACC_STATIC, "test", "()I", null, null);
   267         {
   110             mv.visitCode();
   268             mv = cw.visitMethod(ACC_PUBLIC + ACC_STATIC, "test", "(Lp/I;)I", null, null);
   111             mv.visitLdcInsn(new Handle(Opcodes.H_INVOKEINTERFACE, "I", "m", "()I"));
   269             mv.visitCode();
   112             mv.visitTypeInsn(NEW, "D");
   270             mv.visitLdcInsn(new Handle(Opcodes.H_INVOKEINTERFACE, "p/I", "m", "()I"));
   113             mv.visitInsn(DUP);
   271             mv.visitVarInsn(ALOAD, 0);
   114             mv.visitMethodInsn(INVOKESPECIAL, "D", "<init>", "()V");
   272             mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/invoke/MethodHandle",
   115             mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/invoke/MethodHandle", "invokeExact", "(LI;)I");
   273                     "invokeExact", "(Lp/I;)I");
   116             mv.visitInsn(IRETURN);
   274             mv.visitInsn(IRETURN);
   117             mv.visitMaxs(0,0);
   275             mv.visitMaxs(0, 0);
       
   276             mv.visitEnd();
       
   277         }
       
   278         // static int test(I,11args)
       
   279         {
       
   280             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);
       
   281             mv.visitCode();
       
   282             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"));
       
   283             mv.visitVarInsn(ALOAD, 0);
       
   284             mv.visitVarInsn(ILOAD, 1);
       
   285             mv.visitVarInsn(ILOAD, 2);
       
   286             mv.visitVarInsn(ILOAD, 3);
       
   287             mv.visitVarInsn(ILOAD, 4);
       
   288             mv.visitVarInsn(LLOAD, 5);
       
   289             mv.visitVarInsn(ALOAD, 7);
       
   290             mv.visitVarInsn(ALOAD, 8);
       
   291             mv.visitVarInsn(ALOAD, 9);
       
   292             mv.visitVarInsn(ALOAD, 10);
       
   293             mv.visitVarInsn(ALOAD, 11);
       
   294             mv.visitVarInsn(ALOAD, 12);
       
   295             mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/invoke/MethodHandle",
       
   296                     "invokeExact", "(Lp/I;BCSIJLjava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)I");
       
   297             mv.visitInsn(IRETURN);
       
   298             mv.visitMaxs(0, 0);
   118             mv.visitEnd();
   299             mv.visitEnd();
   119         }
   300         }
   120         cw.visitEnd();
   301         cw.visitEnd();
   121         return cw.toByteArray();
   302         return cw.toByteArray();
   122     }
   303     }
   123 
   304 
   124     public static void main(String args[] ) throws Throwable {
   305     private static void tryAndCheckThrown(
   125         ByteClassLoader bcl = new ByteClassLoader();
   306             List<Throwable> lt, byte[] dBytes, String what, Class<?> expected, String jar_name)
   126         Class<?> d = bcl.loadBytes("D", bytesForD());
   307             throws Throwable {
   127         Class<?> t = bcl.loadBytes("T", bytesForT());
   308         tryAndCheckThrown(lt, "p.D", dBytes, what, expected, jar_name);
       
   309     }
       
   310 
       
   311     private static void tryAndCheckThrown(List<Throwable> lt, String d_name, byte[] dBytes, String what, Class<?> expected, String jar_name)
       
   312             throws Throwable {
       
   313 
       
   314         System.out.println("Methodhandle invokeExact I.m() for instance of " + what);
       
   315         ByteClassLoader bcl1 = new ByteClassLoader(jar_name, readJarFiles, writeJarFiles);
   128         try {
   316         try {
   129           Object result = t.getMethod("test").invoke(null);
   317             Class<?> d1 = bcl1.loadBytes(d_name, dBytes);
   130           System.out.println("Expected AbstractMethodError wrapped in InvocationTargetException, saw no exception");
   318             Class<?> t1 = bcl1.loadBytes("p.T", bytesForT());
   131           throw new Error("Missing expected exception");
   319             invokeTest(t1, d1, expected, lt);
       
   320         } finally {
       
   321             // Not necessary for others -- all class files are written in this call.
       
   322             // (unless the VM crashes first).
       
   323             bcl1.close();
       
   324         }
       
   325 
       
   326         System.out.println("Reflection invoke I.m() for instance of " + what);
       
   327         ByteClassLoader bcl3 = new ByteClassLoader(jar_name, readJarFiles, false);
       
   328         Class<?> d3 = bcl3.loadBytes(d_name, dBytes);
       
   329         Class<?> t3 = bcl3.loadClass("p.Treflect");
       
   330         invokeTest(t3, d3, expected, lt);
       
   331 
       
   332         System.out.println("Bytecode invokeInterface I.m() for instance of " + what);
       
   333         ByteClassLoader bcl2 = new ByteClassLoader(jar_name, readJarFiles, false);
       
   334         Class<?> d2 = bcl2.loadBytes(d_name, dBytes);
       
   335         Class<?> t2 = bcl2.loadClass("p.Tdirect");
       
   336         badGoodBadGood(t2, d2, expected, lt);
       
   337     }
       
   338 
       
   339     private static void invokeTest(Class<?> t, Class<?> d, Class<?> expected, List<Throwable> lt)
       
   340             throws Throwable {
       
   341         try {
       
   342             Method m = t.getMethod("test", p.I.class);
       
   343             Object o = d.newInstance();
       
   344             Object result = m.invoke(null, o);
       
   345             if (expected != null) {
       
   346                 System.out.println("FAIL, Expected " + expected.getName()
       
   347                         + " wrapped in InvocationTargetException, but nothing was thrown");
       
   348                 lt.add(new Error("Exception " + expected.getName() + " was not thrown"));
       
   349             } else {
       
   350                 System.out.println("PASS, saw expected return.");
       
   351             }
   132         } catch (InvocationTargetException e) {
   352         } catch (InvocationTargetException e) {
   133             Throwable th = e.getCause();
   353             Throwable th = e.getCause();
   134             if (th instanceof AbstractMethodError) {
   354             th.printStackTrace(System.out);
   135                 th.printStackTrace(System.out);
   355             if (expected != null) {
   136                 System.out.println("PASS, saw expected exception (AbstractMethodError, wrapped in InvocationTargetException).");
   356                 if (expected.isInstance(th)) {
       
   357                     System.out.println("PASS, saw expected exception (" + expected.getName() + ").");
       
   358                 } else {
       
   359                     System.out.println("FAIL, Expected " + expected.getName()
       
   360                             + " wrapped in InvocationTargetException, saw " + th);
       
   361                     lt.add(th);
       
   362                 }
   137             } else {
   363             } else {
   138                 System.out.println("Expected AbstractMethodError wrapped in InvocationTargetException, saw " + th);
   364                 System.out.println("FAIL, expected no exception, saw " + th);
   139                 throw th;
   365                 lt.add(th);
   140             }
   366             }
   141         }
   367         }
       
   368         System.out.println();
       
   369     }
       
   370 
       
   371     /* Many-arg versions of above */
       
   372     private static void tryAndCheckThrownMany(List<Throwable> lt, byte[] dBytes, String what, Class<?> expected)
       
   373             throws Throwable {
       
   374 
       
   375         System.out.println("Methodhandle invokeExact I.m(11params) for instance of " + what);
       
   376         ByteClassLoader bcl1 = new ByteClassLoader("p.D", readJarFiles, false);
       
   377         try {
       
   378             Class<?> d1 = bcl1.loadBytes("p.D", dBytes);
       
   379             Class<?> t1 = bcl1.loadBytes("p.T", bytesForT());
       
   380             invokeTestMany(t1, d1, expected, lt);
       
   381         } finally {
       
   382             bcl1.close(); // Not necessary for others -- all class files are written in this call.
       
   383         }
       
   384 
       
   385         {
       
   386             System.out.println("Bytecode invokeInterface I.m(11params) for instance of " + what);
       
   387             ByteClassLoader bcl2 = new ByteClassLoader("pD_m_pri_imp_pI", readJarFiles, false);
       
   388             Class<?> d2 = bcl2.loadBytes("p.D", dBytes);
       
   389             Class<?> t2 = bcl2.loadClass("p.Tdirect");
       
   390             badGoodBadGoodMany(t2, d2, expected, lt);
       
   391 
       
   392         }
       
   393         {
       
   394             System.out.println("Reflection invokeInterface I.m(11params) for instance of " + what);
       
   395             ByteClassLoader bcl2 = new ByteClassLoader("pD_m_pri_imp_pI", readJarFiles, false);
       
   396             Class<?> d2 = bcl2.loadBytes("p.D", dBytes);
       
   397             Class<?> t2 = bcl2.loadClass("p.Treflect");
       
   398             invokeTestMany(t2, d2, expected, lt);
       
   399         }
       
   400     }
       
   401 
       
   402     private static void invokeTestMany(Class<?> t, Class<?> d, Class<?> expected, List<Throwable> lt)
       
   403             throws Throwable {
       
   404         try {
       
   405             Method m = t.getMethod("test", p.I.class,
       
   406                     Byte.TYPE, Character.TYPE, Short.TYPE, Integer.TYPE, Long.TYPE,
       
   407                     Object.class, Object.class, Object.class,
       
   408                     Object.class, Object.class, Object.class);
       
   409             Object o = d.newInstance();
       
   410             Byte b = 1;
       
   411             Character c = 2;
       
   412             Short s = 3;
       
   413             Integer i = 4;
       
   414             Long j = 5L;
       
   415             Object o1 = b;
       
   416             Object o2 = c;
       
   417             Object o3 = s;
       
   418             Object o4 = i;
       
   419             Object o5 = j;
       
   420             Object o6 = "6";
       
   421 
       
   422             Object result = m.invoke(null, o, b, c, s, i, j,
       
   423                     o1, o2, o3, o4, o5, o6);
       
   424             if (expected != null) {
       
   425                 System.out.println("FAIL, Expected " + expected.getName()
       
   426                         + " wrapped in InvocationTargetException, but nothing was thrown");
       
   427                 lt.add(new Error("Exception " + expected.getName()
       
   428                         + " was not thrown"));
       
   429             } else {
       
   430                 System.out.println("PASS, saw expected return.");
       
   431             }
       
   432         } catch (InvocationTargetException e) {
       
   433             Throwable th = e.getCause();
       
   434             th.printStackTrace(System.out);
       
   435             if (expected != null) {
       
   436                 if (expected.isInstance(th)) {
       
   437                     System.out.println("PASS, saw expected exception ("
       
   438                             + expected.getName() + ").");
       
   439                 } else {
       
   440                     System.out.println("FAIL, Expected " + expected.getName()
       
   441                             + " wrapped in InvocationTargetException, saw " + th);
       
   442                     lt.add(th);
       
   443                 }
       
   444             } else {
       
   445                 System.out.println("FAIL, expected no exception, saw " + th);
       
   446                 lt.add(th);
       
   447             }
       
   448         }
       
   449         System.out.println();
       
   450     }
       
   451 
       
   452     /**
       
   453      * This tests a peculiar idiom for tickling the bug on older VMs that lack
       
   454      * methodhandles.  The bug (if not fixed) acts in the following way:
       
   455      *
       
   456      *  When a broken receiver is passed to the first execution of an invokeinterface
       
   457      * bytecode, the illegal access is detected before the effects of resolution are
       
   458      * cached for later use, and so repeated calls with a broken receiver will always
       
   459      * throw the correct error.
       
   460      *
       
   461      * If, however, a good receiver is passed to the invokeinterface, the effects of
       
   462      * resolution will be successfully cached.  A subsequent execution with a broken
       
   463      * receiver will reuse the cached information, skip the detailed resolution work,
       
   464      * and instead encounter a null pointer.  By convention, that is the encoding for a
       
   465      * missing abstract method, and an AbstractMethodError is thrown -- not the expected
       
   466      * IllegalAccessError.
       
   467      *
       
   468      * @param t2 Test invocation class
       
   469      * @param d2 Test receiver class
       
   470      * @param expected expected exception type
       
   471      * @param lt list of unexpected throwables seen
       
   472      */
       
   473     private static void badGoodBadGood(Class<?> t2, Class<?> d2, Class<?> expected, List<Throwable> lt)
       
   474             throws Throwable {
       
   475         System.out.println("  Error input 1st time");
       
   476         invokeTest(t2, d2, expected, lt);
       
   477         System.out.println("  Good input (instance of Dok)");
       
   478         invokeTest(t2, Dok.class, null, lt);
       
   479         System.out.println("  Error input 2nd time");
       
   480         invokeTest(t2, d2, expected, lt);
       
   481         System.out.println("  Good input (instance of Dok)");
       
   482         invokeTest(t2, Dok.class, null, lt);
       
   483     }
       
   484 
       
   485     private static void badGoodBadGoodMany(Class<?> t2, Class<?> d2, Class<?> expected, List<Throwable> lt)
       
   486             throws Throwable {
       
   487         System.out.println("  Error input 1st time");
       
   488         invokeTestMany(t2, d2, expected, lt);
       
   489         System.out.println("  Good input (instance of Dok)");
       
   490         invokeTestMany(t2, Dok.class, null, lt);
       
   491         System.out.println("  Error input 2nd time");
       
   492         invokeTestMany(t2, d2, expected, lt);
       
   493         System.out.println("  Good input (instance of Dok)");
       
   494         invokeTestMany(t2, Dok.class, null, lt);
   142     }
   495     }
   143 }
   496 }