1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/test/compiler/jsr292/methodHandleExceptions/TestAMEnotNPE.java Wed Apr 27 01:25:04 2016 +0800 1.3 @@ -0,0 +1,496 @@ 1.4 +/* 1.5 + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. 1.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 1.7 + * 1.8 + * This code is free software; you can redistribute it and/or modify it 1.9 + * under the terms of the GNU General Public License version 2 only, as 1.10 + * published by the Free Software Foundation. 1.11 + * 1.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 1.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 1.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 1.15 + * version 2 for more details (a copy is included in the LICENSE file that 1.16 + * accompanied this code). 1.17 + * 1.18 + * You should have received a copy of the GNU General Public License version 1.19 + * 2 along with this work; if not, write to the Free Software Foundation, 1.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 1.21 + * 1.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 1.23 + * or visit www.oracle.com if you need additional information or have any 1.24 + * questions. 1.25 + * 1.26 + */ 1.27 +import java.lang.reflect.InvocationTargetException; 1.28 +import java.lang.reflect.Method; 1.29 +import java.util.ArrayList; 1.30 +import java.util.List; 1.31 +import jdk.internal.org.objectweb.asm.ClassWriter; 1.32 +import jdk.internal.org.objectweb.asm.Handle; 1.33 +import jdk.internal.org.objectweb.asm.MethodVisitor; 1.34 +import jdk.internal.org.objectweb.asm.Opcodes; 1.35 +import p.Dok; 1.36 + 1.37 +/** 1.38 + * @test @bug 8025260 8016839 1.39 + * @summary Ensure that AbstractMethodError and IllegalAccessError are thrown appropriately, not NullPointerException 1.40 + * 1.41 + * @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 1.42 + * 1.43 + * @run main/othervm TestAMEnotNPE 1.44 + * @run main/othervm -Xint TestAMEnotNPE 1.45 + * @run main/othervm -Xcomp TestAMEnotNPE 1.46 + */ 1.47 +public class TestAMEnotNPE implements Opcodes { 1.48 + 1.49 + static boolean writeJarFiles = false; 1.50 + static boolean readJarFiles = false; 1.51 + 1.52 + /** 1.53 + * Optional command line parameter (any case-insensitive prefix of) 1.54 + * "writejarfiles" or "readjarfiles". 1.55 + * 1.56 + * "Writejarfiles" creates a jar file for each different set of tested classes. 1.57 + * "Readjarfiles" causes the classloader to use the copies of the classes 1.58 + * found in the corresponding jar files. 1.59 + * 1.60 + * Jarfilenames look something like pD_ext_pF (p.D extends p.F) 1.61 + * and qD_m_pp_imp_pI (q.D with package-private m implements p.I) 1.62 + * 1.63 + */ 1.64 + public static void main(String args[]) throws Throwable { 1.65 + ArrayList<Throwable> lt = new ArrayList<Throwable>(); 1.66 + 1.67 + if (args.length > 0) { 1.68 + String a0 = args[0].toLowerCase(); 1.69 + if (a0.length() > 0) { 1.70 + writeJarFiles = ("writejarfiles").startsWith(a0); 1.71 + readJarFiles = ("readjarfiles").startsWith(a0); 1.72 + } 1.73 + if (!(writeJarFiles || readJarFiles)) { 1.74 + throw new Error("Command line parameter (if any) should be prefix of writeJarFiles or readJarFiles"); 1.75 + } 1.76 + } 1.77 + 1.78 + try { 1.79 + System.out.println("TRYING p.D.m PRIVATE interface-invoked as p.I.m, p.D extends p.F, p.F.m FINAL"); 1.80 + tryAndCheckThrown(lt, bytesForDprivateSubWhat("p/F"), 1.81 + "p.D extends p.F (p.F implements p.I, FINAL public m), private m", 1.82 + IllegalAccessError.class, "pD_ext_pF"); 1.83 + // We'll take either a VerifyError (pre 2013-11-30) 1.84 + // or an IllegalAccessError (post 2013-11-22) 1.85 + } catch (VerifyError ve) { 1.86 + System.out.println("Saw expected VerifyError " + ve); 1.87 + } 1.88 + System.out.println(); 1.89 + 1.90 + System.out.println("TRYING p.D.m PRIVATE interface-invoked as p.I.m, p.D extends p.E"); 1.91 + tryAndCheckThrown(lt, bytesForDprivateSubWhat("p/E"), 1.92 + "p.D extends p.E (p.E implements p.I, public m), private m", 1.93 + IllegalAccessError.class, "pD_ext_pE"); 1.94 + 1.95 + System.out.println("TRYING p.D.m ABSTRACT interface-invoked as p.I.m"); 1.96 + tryAndCheckThrown(lt, bytesForD(), 1.97 + "D extends abstract C, no m", 1.98 + AbstractMethodError.class, "pD_ext_pC"); 1.99 + 1.100 + System.out.println("TRYING q.D.m PACKAGE interface-invoked as p.I.m"); 1.101 + tryAndCheckThrown(lt, "q.D", bytesForDsomeAccess("q/D", 0), 1.102 + "q.D implements p.I, protected m", IllegalAccessError.class, 1.103 + "qD_m_pp_imp_pI"); 1.104 + 1.105 + // Note jar file name is used in the plural-arg case. 1.106 + System.out.println("TRYING p.D.m PRIVATE interface-invoked as p.I.m"); 1.107 + tryAndCheckThrown(lt, bytesForDsomeAccess("p/D", ACC_PRIVATE), 1.108 + "p.D implements p.I, private m", 1.109 + IllegalAccessError.class, "pD_m_pri_imp_pI"); 1.110 + 1.111 + // Plural-arg test. 1.112 + System.out.println("TRYING p.D.m PRIVATE MANY ARG interface-invoked as p.I.m"); 1.113 + tryAndCheckThrownMany(lt, bytesForDsomeAccess("p/D", ACC_PRIVATE), 1.114 + "p.D implements p.I, private m", IllegalAccessError.class); 1.115 + 1.116 + if (lt.size() > 0) { 1.117 + System.out.flush(); 1.118 + Thread.sleep(250); // This de-interleaves output and error in Netbeans, sigh. 1.119 + for (Throwable th : lt) 1.120 + System.err.println(th); 1.121 + throw new Error("Test failed, there were " + lt.size() + " failures listed above"); 1.122 + } else { 1.123 + System.out.println("ALL PASS, HOORAY!"); 1.124 + } 1.125 + } 1.126 + 1.127 + /** 1.128 + * The bytes for D, a NOT abstract class extending abstract class C without 1.129 + * supplying an implementation for abstract method m. There is a default 1.130 + * method in the interface I, but it should lose to the abstract class. 1.131 + * 1.132 + * @return 1.133 + * @throws Exception 1.134 + */ 1.135 + public static byte[] bytesForD() throws Exception { 1.136 + 1.137 + ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES 1.138 + | ClassWriter.COMPUTE_MAXS); 1.139 + MethodVisitor mv; 1.140 + 1.141 + cw.visit(V1_8, ACC_PUBLIC + ACC_SUPER, "p/D", null, "p/C", null); 1.142 + 1.143 + { 1.144 + mv = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null); 1.145 + mv.visitCode(); 1.146 + mv.visitVarInsn(ALOAD, 0); 1.147 + mv.visitMethodInsn(INVOKESPECIAL, "p/C", "<init>", "()V"); 1.148 + mv.visitInsn(RETURN); 1.149 + mv.visitMaxs(0, 0); 1.150 + mv.visitEnd(); 1.151 + } 1.152 + cw.visitEnd(); 1.153 + 1.154 + return cw.toByteArray(); 1.155 + } 1.156 + 1.157 + /** 1.158 + * The bytes for D, implements I, does not extend C, declares m()I with 1.159 + * access method_acc. 1.160 + * 1.161 + * @param d_name Name of class defined 1.162 + * @param method_acc Accessibility of that class's method m. 1.163 + * @return 1.164 + * @throws Exception 1.165 + */ 1.166 + public static byte[] bytesForDsomeAccess(String d_name, int method_acc) throws Exception { 1.167 + return bytesForSomeDsubSomethingSomeAccess(d_name, "java/lang/Object", method_acc); 1.168 + } 1.169 + 1.170 + /** 1.171 + * The bytes for D implements I, extends some class, declares m()I as 1.172 + * private. 1.173 + * 1.174 + * Invokeinterface of I.m applied to this D should throw IllegalAccessError 1.175 + * 1.176 + * @param sub_what The name of the class that D will extend. 1.177 + * @return 1.178 + * @throws Exception 1.179 + */ 1.180 + public static byte[] bytesForDprivateSubWhat(String sub_what) throws Exception { 1.181 + return bytesForSomeDsubSomethingSomeAccess("p/D", sub_what, ACC_PRIVATE); 1.182 + } 1.183 + 1.184 + /** 1.185 + * Returns the bytes for a class with name d_name (presumably "D" in some 1.186 + * package), extending some class with name sub_what, implementing p.I, 1.187 + * and defining two methods m() and m(11args) with access method_acc. 1.188 + * 1.189 + * @param d_name Name of class that is defined 1.190 + * @param sub_what Name of class that it extends 1.191 + * @param method_acc Accessibility of method(s) m in defined class. 1.192 + * @return 1.193 + * @throws Exception 1.194 + */ 1.195 + public static byte[] bytesForSomeDsubSomethingSomeAccess 1.196 + (String d_name, String sub_what, int method_acc) 1.197 + throws Exception { 1.198 + 1.199 + ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES 1.200 + | ClassWriter.COMPUTE_MAXS); 1.201 + MethodVisitor mv; 1.202 + String[] interfaces = {"p/I"}; 1.203 + 1.204 + cw.visit(V1_8, ACC_PUBLIC + ACC_SUPER, d_name, null, sub_what, interfaces); 1.205 + { 1.206 + mv = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null); 1.207 + mv.visitCode(); 1.208 + mv.visitVarInsn(ALOAD, 0); 1.209 + mv.visitMethodInsn(INVOKESPECIAL, sub_what, "<init>", "()V"); 1.210 + mv.visitInsn(RETURN); 1.211 + mv.visitMaxs(0, 0); 1.212 + mv.visitEnd(); 1.213 + } 1.214 + // int m() {return 3;} 1.215 + { 1.216 + mv = cw.visitMethod(method_acc, "m", "()I", null, null); 1.217 + mv.visitCode(); 1.218 + mv.visitLdcInsn(new Integer(3)); 1.219 + mv.visitInsn(IRETURN); 1.220 + mv.visitMaxs(0, 0); 1.221 + mv.visitEnd(); 1.222 + } 1.223 + // int m(11args) {return 3;} 1.224 + { 1.225 + mv = cw.visitMethod(method_acc, "m", "(BCSIJ" 1.226 + + "Ljava/lang/Object;" 1.227 + + "Ljava/lang/Object;" 1.228 + + "Ljava/lang/Object;" 1.229 + + "Ljava/lang/Object;" 1.230 + + "Ljava/lang/Object;" 1.231 + + "Ljava/lang/Object;" 1.232 + + ")I", null, null); 1.233 + mv.visitCode(); 1.234 + mv.visitLdcInsn(new Integer(3)); 1.235 + mv.visitInsn(IRETURN); 1.236 + mv.visitMaxs(0, 0); 1.237 + mv.visitEnd(); 1.238 + } 1.239 + cw.visitEnd(); 1.240 + return cw.toByteArray(); 1.241 + } 1.242 + 1.243 + /** 1.244 + * The bytecodes for a class p/T defining a methods test() and test(11args) 1.245 + * that contain an invokeExact of a particular methodHandle, I.m. 1.246 + * 1.247 + * Test will be passed values that may imperfectly implement I, 1.248 + * and thus may in turn throw exceptions. 1.249 + * 1.250 + * @return 1.251 + * @throws Exception 1.252 + */ 1.253 + public static byte[] bytesForT() throws Exception { 1.254 + 1.255 + ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES 1.256 + | ClassWriter.COMPUTE_MAXS); 1.257 + MethodVisitor mv; 1.258 + 1.259 + cw.visit(V1_8, ACC_PUBLIC + ACC_SUPER, "p/T", null, "java/lang/Object", null); 1.260 + { 1.261 + mv = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null); 1.262 + mv.visitCode(); 1.263 + mv.visitVarInsn(ALOAD, 0); 1.264 + mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V"); 1.265 + mv.visitInsn(RETURN); 1.266 + mv.visitMaxs(0, 0); 1.267 + mv.visitEnd(); 1.268 + } 1.269 + // static int test(I) 1.270 + { 1.271 + mv = cw.visitMethod(ACC_PUBLIC + ACC_STATIC, "test", "(Lp/I;)I", null, null); 1.272 + mv.visitCode(); 1.273 + mv.visitLdcInsn(new Handle(Opcodes.H_INVOKEINTERFACE, "p/I", "m", "()I")); 1.274 + mv.visitVarInsn(ALOAD, 0); 1.275 + mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/invoke/MethodHandle", 1.276 + "invokeExact", "(Lp/I;)I"); 1.277 + mv.visitInsn(IRETURN); 1.278 + mv.visitMaxs(0, 0); 1.279 + mv.visitEnd(); 1.280 + } 1.281 + // static int test(I,11args) 1.282 + { 1.283 + 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); 1.284 + mv.visitCode(); 1.285 + 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")); 1.286 + mv.visitVarInsn(ALOAD, 0); 1.287 + mv.visitVarInsn(ILOAD, 1); 1.288 + mv.visitVarInsn(ILOAD, 2); 1.289 + mv.visitVarInsn(ILOAD, 3); 1.290 + mv.visitVarInsn(ILOAD, 4); 1.291 + mv.visitVarInsn(LLOAD, 5); 1.292 + mv.visitVarInsn(ALOAD, 7); 1.293 + mv.visitVarInsn(ALOAD, 8); 1.294 + mv.visitVarInsn(ALOAD, 9); 1.295 + mv.visitVarInsn(ALOAD, 10); 1.296 + mv.visitVarInsn(ALOAD, 11); 1.297 + mv.visitVarInsn(ALOAD, 12); 1.298 + mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/invoke/MethodHandle", 1.299 + "invokeExact", "(Lp/I;BCSIJLjava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)I"); 1.300 + mv.visitInsn(IRETURN); 1.301 + mv.visitMaxs(0, 0); 1.302 + mv.visitEnd(); 1.303 + } 1.304 + cw.visitEnd(); 1.305 + return cw.toByteArray(); 1.306 + } 1.307 + 1.308 + private static void tryAndCheckThrown( 1.309 + List<Throwable> lt, byte[] dBytes, String what, Class<?> expected, String jar_name) 1.310 + throws Throwable { 1.311 + tryAndCheckThrown(lt, "p.D", dBytes, what, expected, jar_name); 1.312 + } 1.313 + 1.314 + private static void tryAndCheckThrown(List<Throwable> lt, String d_name, byte[] dBytes, String what, Class<?> expected, String jar_name) 1.315 + throws Throwable { 1.316 + 1.317 + System.out.println("Methodhandle invokeExact I.m() for instance of " + what); 1.318 + ByteClassLoader bcl1 = new ByteClassLoader(jar_name, readJarFiles, writeJarFiles); 1.319 + try { 1.320 + Class<?> d1 = bcl1.loadBytes(d_name, dBytes); 1.321 + Class<?> t1 = bcl1.loadBytes("p.T", bytesForT()); 1.322 + invokeTest(t1, d1, expected, lt); 1.323 + } finally { 1.324 + // Not necessary for others -- all class files are written in this call. 1.325 + // (unless the VM crashes first). 1.326 + bcl1.close(); 1.327 + } 1.328 + 1.329 + System.out.println("Reflection invoke I.m() for instance of " + what); 1.330 + ByteClassLoader bcl3 = new ByteClassLoader(jar_name, readJarFiles, false); 1.331 + Class<?> d3 = bcl3.loadBytes(d_name, dBytes); 1.332 + Class<?> t3 = bcl3.loadClass("p.Treflect"); 1.333 + invokeTest(t3, d3, expected, lt); 1.334 + 1.335 + System.out.println("Bytecode invokeInterface I.m() for instance of " + what); 1.336 + ByteClassLoader bcl2 = new ByteClassLoader(jar_name, readJarFiles, false); 1.337 + Class<?> d2 = bcl2.loadBytes(d_name, dBytes); 1.338 + Class<?> t2 = bcl2.loadClass("p.Tdirect"); 1.339 + badGoodBadGood(t2, d2, expected, lt); 1.340 + } 1.341 + 1.342 + private static void invokeTest(Class<?> t, Class<?> d, Class<?> expected, List<Throwable> lt) 1.343 + throws Throwable { 1.344 + try { 1.345 + Method m = t.getMethod("test", p.I.class); 1.346 + Object o = d.newInstance(); 1.347 + Object result = m.invoke(null, o); 1.348 + if (expected != null) { 1.349 + System.out.println("FAIL, Expected " + expected.getName() 1.350 + + " wrapped in InvocationTargetException, but nothing was thrown"); 1.351 + lt.add(new Error("Exception " + expected.getName() + " was not thrown")); 1.352 + } else { 1.353 + System.out.println("PASS, saw expected return."); 1.354 + } 1.355 + } catch (InvocationTargetException e) { 1.356 + Throwable th = e.getCause(); 1.357 + th.printStackTrace(System.out); 1.358 + if (expected != null) { 1.359 + if (expected.isInstance(th)) { 1.360 + System.out.println("PASS, saw expected exception (" + expected.getName() + ")."); 1.361 + } else { 1.362 + System.out.println("FAIL, Expected " + expected.getName() 1.363 + + " wrapped in InvocationTargetException, saw " + th); 1.364 + lt.add(th); 1.365 + } 1.366 + } else { 1.367 + System.out.println("FAIL, expected no exception, saw " + th); 1.368 + lt.add(th); 1.369 + } 1.370 + } 1.371 + System.out.println(); 1.372 + } 1.373 + 1.374 + /* Many-arg versions of above */ 1.375 + private static void tryAndCheckThrownMany(List<Throwable> lt, byte[] dBytes, String what, Class<?> expected) 1.376 + throws Throwable { 1.377 + 1.378 + System.out.println("Methodhandle invokeExact I.m(11params) for instance of " + what); 1.379 + ByteClassLoader bcl1 = new ByteClassLoader("p.D", readJarFiles, false); 1.380 + try { 1.381 + Class<?> d1 = bcl1.loadBytes("p.D", dBytes); 1.382 + Class<?> t1 = bcl1.loadBytes("p.T", bytesForT()); 1.383 + invokeTestMany(t1, d1, expected, lt); 1.384 + } finally { 1.385 + bcl1.close(); // Not necessary for others -- all class files are written in this call. 1.386 + } 1.387 + 1.388 + { 1.389 + System.out.println("Bytecode invokeInterface I.m(11params) for instance of " + what); 1.390 + ByteClassLoader bcl2 = new ByteClassLoader("pD_m_pri_imp_pI", readJarFiles, false); 1.391 + Class<?> d2 = bcl2.loadBytes("p.D", dBytes); 1.392 + Class<?> t2 = bcl2.loadClass("p.Tdirect"); 1.393 + badGoodBadGoodMany(t2, d2, expected, lt); 1.394 + 1.395 + } 1.396 + { 1.397 + System.out.println("Reflection invokeInterface I.m(11params) for instance of " + what); 1.398 + ByteClassLoader bcl2 = new ByteClassLoader("pD_m_pri_imp_pI", readJarFiles, false); 1.399 + Class<?> d2 = bcl2.loadBytes("p.D", dBytes); 1.400 + Class<?> t2 = bcl2.loadClass("p.Treflect"); 1.401 + invokeTestMany(t2, d2, expected, lt); 1.402 + } 1.403 + } 1.404 + 1.405 + private static void invokeTestMany(Class<?> t, Class<?> d, Class<?> expected, List<Throwable> lt) 1.406 + throws Throwable { 1.407 + try { 1.408 + Method m = t.getMethod("test", p.I.class, 1.409 + Byte.TYPE, Character.TYPE, Short.TYPE, Integer.TYPE, Long.TYPE, 1.410 + Object.class, Object.class, Object.class, 1.411 + Object.class, Object.class, Object.class); 1.412 + Object o = d.newInstance(); 1.413 + Byte b = 1; 1.414 + Character c = 2; 1.415 + Short s = 3; 1.416 + Integer i = 4; 1.417 + Long j = 5L; 1.418 + Object o1 = b; 1.419 + Object o2 = c; 1.420 + Object o3 = s; 1.421 + Object o4 = i; 1.422 + Object o5 = j; 1.423 + Object o6 = "6"; 1.424 + 1.425 + Object result = m.invoke(null, o, b, c, s, i, j, 1.426 + o1, o2, o3, o4, o5, o6); 1.427 + if (expected != null) { 1.428 + System.out.println("FAIL, Expected " + expected.getName() 1.429 + + " wrapped in InvocationTargetException, but nothing was thrown"); 1.430 + lt.add(new Error("Exception " + expected.getName() 1.431 + + " was not thrown")); 1.432 + } else { 1.433 + System.out.println("PASS, saw expected return."); 1.434 + } 1.435 + } catch (InvocationTargetException e) { 1.436 + Throwable th = e.getCause(); 1.437 + th.printStackTrace(System.out); 1.438 + if (expected != null) { 1.439 + if (expected.isInstance(th)) { 1.440 + System.out.println("PASS, saw expected exception (" 1.441 + + expected.getName() + ")."); 1.442 + } else { 1.443 + System.out.println("FAIL, Expected " + expected.getName() 1.444 + + " wrapped in InvocationTargetException, saw " + th); 1.445 + lt.add(th); 1.446 + } 1.447 + } else { 1.448 + System.out.println("FAIL, expected no exception, saw " + th); 1.449 + lt.add(th); 1.450 + } 1.451 + } 1.452 + System.out.println(); 1.453 + } 1.454 + 1.455 + /** 1.456 + * This tests a peculiar idiom for tickling the bug on older VMs that lack 1.457 + * methodhandles. The bug (if not fixed) acts in the following way: 1.458 + * 1.459 + * When a broken receiver is passed to the first execution of an invokeinterface 1.460 + * bytecode, the illegal access is detected before the effects of resolution are 1.461 + * cached for later use, and so repeated calls with a broken receiver will always 1.462 + * throw the correct error. 1.463 + * 1.464 + * If, however, a good receiver is passed to the invokeinterface, the effects of 1.465 + * resolution will be successfully cached. A subsequent execution with a broken 1.466 + * receiver will reuse the cached information, skip the detailed resolution work, 1.467 + * and instead encounter a null pointer. By convention, that is the encoding for a 1.468 + * missing abstract method, and an AbstractMethodError is thrown -- not the expected 1.469 + * IllegalAccessError. 1.470 + * 1.471 + * @param t2 Test invocation class 1.472 + * @param d2 Test receiver class 1.473 + * @param expected expected exception type 1.474 + * @param lt list of unexpected throwables seen 1.475 + */ 1.476 + private static void badGoodBadGood(Class<?> t2, Class<?> d2, Class<?> expected, List<Throwable> lt) 1.477 + throws Throwable { 1.478 + System.out.println(" Error input 1st time"); 1.479 + invokeTest(t2, d2, expected, lt); 1.480 + System.out.println(" Good input (instance of Dok)"); 1.481 + invokeTest(t2, Dok.class, null, lt); 1.482 + System.out.println(" Error input 2nd time"); 1.483 + invokeTest(t2, d2, expected, lt); 1.484 + System.out.println(" Good input (instance of Dok)"); 1.485 + invokeTest(t2, Dok.class, null, lt); 1.486 + } 1.487 + 1.488 + private static void badGoodBadGoodMany(Class<?> t2, Class<?> d2, Class<?> expected, List<Throwable> lt) 1.489 + throws Throwable { 1.490 + System.out.println(" Error input 1st time"); 1.491 + invokeTestMany(t2, d2, expected, lt); 1.492 + System.out.println(" Good input (instance of Dok)"); 1.493 + invokeTestMany(t2, Dok.class, null, lt); 1.494 + System.out.println(" Error input 2nd time"); 1.495 + invokeTestMany(t2, d2, expected, lt); 1.496 + System.out.println(" Good input (instance of Dok)"); 1.497 + invokeTestMany(t2, Dok.class, null, lt); 1.498 + } 1.499 +}