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