1 /*
   2  * Copyright (c) 2017, 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 8046171
  27  * @summary Test access to private methods between nestmates where there
  28  *          is an inheritance hierarchy and we invoke private methods that
  29  *          exist in specific classes in the hierarchy.
  30  * @run main TestReflectionHierarchy
  31  * @run main/othervm -Dsun.reflect.noInflation=true TestReflectionHierarchy
  32  */
  33 
  34 // The first run will use NativeMethodAccessor and due to the limited number
  35 // of calls we will not reach the inflation threshold.
  36 // The second run disables inflation so we will use the GeneratedMethodAccessor
  37 // instead. In this way both sets of Reflection classes are tested.
  38 
  39 
  40 public class TestReflectionHierarchy {
  41 
  42     static class NestedA extends ExternalSuper {
  43         static final String ID =  "NestedA::priv_invoke";
  44         private String priv_invoke() {
  45             return ID;
  46         }
  47         static void checkA(NestedA a) throws Throwable {
  48             verifyEquals((String)NestedA.class.
  49                          getDeclaredMethod("priv_invoke",
  50                                            new Class<?>[0]).
  51                          invoke(a, new Object[0]),
  52                          NestedA.ID);
  53         }
  54     }
  55 
  56     static class NestedB extends NestedA {
  57         static final String ID =  "NestedB::priv_invoke";
  58         private String priv_invoke() {
  59             return ID;
  60         }
  61         static void checkA(NestedA a) throws Throwable {
  62             verifyEquals((String)NestedA.class.
  63                          getDeclaredMethod("priv_invoke",
  64                                            new Class<?>[0]).
  65                          invoke(a, new Object[0]),
  66                          NestedA.ID);
  67         }
  68     }
  69 
  70     static class NestedC extends NestedB {
  71         static final String ID =  "NestedC::priv_invoke";
  72         private String priv_invoke() {
  73             return ID;
  74         }
  75         static void checkA(NestedA a) throws Throwable {
  76             verifyEquals((String)NestedA.class.
  77                          getDeclaredMethod("priv_invoke",
  78                                            new Class<?>[0]).
  79                          invoke(a, new Object[0]),
  80                          NestedA.ID);
  81         }
  82     }
  83 
  84     static void checkA(NestedA a) throws Throwable {
  85             verifyEquals((String)NestedA.class.
  86                          getDeclaredMethod("priv_invoke",
  87                                            new Class<?>[0]).
  88                          invoke(a, new Object[0]),
  89                          NestedA.ID);
  90     }
  91 
  92     static void checkB(NestedB b) throws Throwable {
  93             verifyEquals((String)NestedB.class.
  94                          getDeclaredMethod("priv_invoke",
  95                                            new Class<?>[0]).
  96                          invoke(b, new Object[0]),
  97                          NestedB.ID);
  98     }
  99 
 100     static void checkC(NestedC c) throws Throwable {
 101             verifyEquals((String)NestedC.class.
 102                          getDeclaredMethod("priv_invoke",
 103                                            new Class<?>[0]).
 104                          invoke(c, new Object[0]),
 105                          NestedC.ID);
 106     }
 107 
 108 
 109     // Access to private members of classes outside the nest is
 110     // not permitted. These tests should throw IllegalAccessException
 111     // at runtime.
 112 
 113     static void checkExternalSuper(ExternalSuper s) throws Throwable {
 114         try {
 115             ExternalSuper.class.
 116                 getDeclaredMethod("priv_invoke", new Class<?>[0]).
 117                 invoke(s, new Object[0]);
 118             throw new Error("Unexpected access to ExternalSuper.priv_invoke");
 119         }
 120         catch (IllegalAccessException iae) {
 121             System.out.println("Got expected exception accessing ExternalSuper.priv_invoke:" + iae);
 122         }
 123     }
 124 
 125     static void checkExternalSub(ExternalSub s) throws Throwable {
 126         try {
 127             ExternalSub.class.
 128                 getDeclaredMethod("priv_invoke", new Class<?>[0]).
 129                 invoke(s, new Object[0]);
 130             throw new Error("Unexpected access to ExternalSub.priv_invoke");
 131         }
 132         catch (IllegalAccessException iae) {
 133             System.out.println("Got expected exception accessing ExternalSub.priv_invoke:" + iae);
 134         }
 135     }
 136 
 137     static void verifyEquals(String actual, String expected) {
 138         if (!actual.equals(expected)) {
 139             throw new Error("Expected " + expected + " but got " + actual);
 140         }
 141         System.out.println("Check passed for " + expected);
 142     }
 143 
 144     public static void main(String[] args) throws Throwable {
 145         NestedA a = new NestedA();
 146         NestedB b = new NestedB();
 147         NestedC c = new NestedC();
 148         ExternalSub sub = new ExternalSub();
 149         ExternalSuper sup = new ExternalSuper();
 150 
 151         checkExternalSuper(sup);
 152         checkExternalSuper(a);
 153         checkExternalSuper(b);
 154         checkExternalSuper(c);
 155         checkExternalSuper(sub);
 156 
 157         checkA(a);
 158         checkA(b);
 159         checkA(c);
 160         checkA(sub);
 161 
 162         NestedA.checkA(a);
 163         NestedA.checkA(b);
 164         NestedA.checkA(c);
 165         NestedA.checkA(sub);
 166 
 167         NestedB.checkA(a);
 168         NestedB.checkA(b);
 169         NestedB.checkA(c);
 170         NestedB.checkA(sub);
 171 
 172         NestedC.checkA(a);
 173         NestedC.checkA(b);
 174         NestedC.checkA(c);
 175         NestedC.checkA(sub);
 176 
 177         checkB(b);
 178         checkB(c);
 179         checkB(sub);
 180 
 181         checkC(c);
 182         checkC(sub);
 183 
 184         checkExternalSub(sub);
 185     }
 186 }
 187 
 188 // Classes that are not part of the nest.
 189 // Being non-public allows us to declare them in this file.
 190 
 191 class ExternalSuper {
 192     static final String ID =  "ExternalSuper::priv_invoke";
 193     private String priv_invoke() {
 194         return ID;
 195     }
 196 }
 197 
 198 
 199 class ExternalSub extends TestReflectionHierarchy.NestedC {
 200     static final String ID =  "ExternalSub::priv_invoke";
 201     private String priv_invoke() {
 202         return ID;
 203     }
 204 }