MHIllegalAccess.java revision 15491:6f390eafc676
1/*
2 * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
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
21 * questions.
22 */
23
24/**
25 * @test
26 * @bug 8022701
27 * @summary Illegal access exceptions via methodhandle invocations threw wrong error.
28 * @modules java.base/jdk.internal.org.objectweb.asm
29 * @compile -XDignore.symbol.file BogoLoader.java InvokeSeveralWays.java MHIllegalAccess.java MethodSupplier.java
30 * @run main/othervm MHIllegalAccess
31 */
32
33import java.lang.reflect.InvocationTargetException;
34import java.util.HashMap;
35import java.util.HashSet;
36import jdk.internal.org.objectweb.asm.ClassWriter;
37import jdk.internal.org.objectweb.asm.MethodVisitor;
38import jdk.internal.org.objectweb.asm.ClassVisitor;
39import jdk.internal.org.objectweb.asm.Opcodes;
40
41public class MHIllegalAccess implements Opcodes {
42
43   public static void main(String args[]) throws Throwable  {
44      System.out.println("Classpath is " + System.getProperty("java.class.path"));
45      System.out.println();
46
47      /**
48       * Make method m be private to provoke an IllegalAccessError.
49       */
50      BogoLoader.VisitorMaker privatize = new BogoLoader.VisitorMaker() {
51           public ClassVisitor make(ClassVisitor cv) {
52               return new ClassVisitor(Opcodes.ASM5, cv) {
53                   public MethodVisitor visitMethod(int access, String name, String desc,
54                           String signature, String[] exceptions) {
55                       if (name.equals("m"))
56                           access = (access | ACC_PRIVATE) & ~ (ACC_PUBLIC | ACC_PROTECTED);
57                           return super.visitMethod(access, name, desc, signature, exceptions);
58                   }
59               };
60           }
61       };
62
63     /**
64       * Rename method m as nemo to provoke a NoSuchMethodError.
65       */
66     BogoLoader.VisitorMaker changeName = new BogoLoader.VisitorMaker() {
67           public ClassVisitor make(ClassVisitor cv) {
68               return new ClassVisitor(Opcodes.ASM5, cv) {
69                   public MethodVisitor visitMethod(int access, String name, String desc,
70                           String signature, String[] exceptions) {
71                       if (name.equals("m"))
72                           name = "nemo";
73                           return super.visitMethod(access, name, desc, signature, exceptions);
74                   }
75               };
76           }
77       };
78
79      int failures = 0;
80      failures += testOneError(privatize, args, IllegalAccessError.class);
81      failures += testOneError(changeName, args, NoSuchMethodError.class);
82      if (failures > 0) {
83          System.out.println("Saw " + failures + " failures, see standard out for details");
84          throw new Error("FAIL test");
85      }
86   }
87
88   /**
89    *
90    * @param vm VisitorMaker, to be stored in a table and passed to a BogoLoader
91    * @param args A copy of the main args, to be passed on to InvokeSeveralWays.test
92    * @param expected The class of the exception that should be thrown after
93    *                 attempted invocation of MethodSupplier.m.
94    * @throws ClassNotFoundException
95    * @throws Throwable
96    */
97    private static int testOneError(BogoLoader.VisitorMaker vm, String[] args, Class expected) throws ClassNotFoundException, Throwable {
98      HashMap<String, BogoLoader.VisitorMaker> replace = new HashMap<String, BogoLoader.VisitorMaker>();
99      replace.put("MethodSupplier", vm);
100
101      HashSet<String> in_bogus = new HashSet<String>();
102        in_bogus.add("InvokeSeveralWays");
103        in_bogus.add("MyFunctionalInterface");
104        in_bogus.add("Invoker");
105
106        BogoLoader bl = new BogoLoader(in_bogus, replace);
107        Class<?> isw = bl.loadClass("InvokeSeveralWays");
108        Object[] arg_for_args = new Object[2];
109        arg_for_args[0] = args;
110        arg_for_args[1] = expected;
111        try {
112            Object result = isw.getMethod("test", String[].class, Class.class).invoke(null, arg_for_args);
113            return (Integer)result;
114        } catch (InvocationTargetException e) {
115            Throwable th = e.getCause();
116            throw th == null ? e : th;
117        }
118    }
119}
120