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 fields between nestmates and nest-top
  28  *          using different flavours of named nested types using method handles
  29  * @compile -XDdisablePrivateAccessors TestMethodHandles.java
  30  * @run main TestMethodHandles
  31  */
  32 
  33 import java.lang.invoke.*;
  34 import static java.lang.invoke.MethodHandles.*;
  35 
  36 public class TestMethodHandles {
  37 
  38     // Private field of nest-top for nestmates to access
  39     private int priv_field;
  40 
  41     // public constructor so we aren't relying on private access
  42     public TestMethodHandles() {}
  43 
  44     // Methods that will access private fields of nestmates
  45 
  46     // NOTE: No StaticIface variants as interfaces can't have instance fields
  47 
  48     void access_priv(TestMethodHandles o) throws Throwable {
  49         MethodHandle mh = lookup().findGetter(o.getClass(), "priv_field", int.class);
  50         this.priv_field = (int) mh.invoke(o);
  51         this.priv_field = (int) mh.invokeExact(o);
  52         checkBadInvokeG(mh, new StaticNested()); // wrong nestmate
  53         checkBadInvokeG(mh, mh); // completely wrong type
  54 
  55         mh = lookup().findSetter(o.getClass(), "priv_field", int.class);
  56         mh.invoke(o, 2);
  57         mh.invokeExact(o, 3);
  58         checkBadInvokeS(mh, new StaticNested()); // wrong nestmate
  59         checkBadInvokeS(mh, mh); // completely wrong type
  60     }
  61     void access_priv(InnerNested o) throws Throwable {
  62         MethodHandle mh = lookup().findGetter(o.getClass(), "priv_field", int.class);
  63         this.priv_field = (int) mh.invoke(o);
  64         this.priv_field = (int) mh.invokeExact(o);
  65         checkBadInvokeG(mh, this); // wrong nestmate
  66         checkBadInvokeG(mh, mh); // completely wrong type
  67 
  68         mh = lookup().findSetter(o.getClass(), "priv_field", int.class);
  69         mh.invoke(o, 2);
  70         mh.invokeExact(o, 3);
  71         checkBadInvokeS(mh, this); // wrong nestmate
  72         checkBadInvokeS(mh, mh); // completely wrong type
  73     }
  74     void access_priv(StaticNested o) throws Throwable {
  75         MethodHandle mh = lookup().findGetter(o.getClass(), "priv_field", int.class);
  76         this.priv_field = (int) mh.invoke(o);
  77         this.priv_field = (int) mh.invokeExact(o);
  78         checkBadInvokeG(mh, this); // wrong nestmate
  79         checkBadInvokeG(mh, mh); // completely wrong type
  80 
  81         mh = lookup().findSetter(o.getClass(), "priv_field", int.class);
  82         mh.invoke(o, 2);
  83         mh.invokeExact(o, 3);
  84         checkBadInvokeS(mh, this); // wrong nestmate
  85         checkBadInvokeS(mh, mh); // completely wrong type
  86     }
  87 
  88     // The various nestmates
  89 
  90     static interface StaticIface {
  91 
  92         // Methods that will access private fields of nestmates
  93 
  94         default void access_priv(TestMethodHandles o) throws Throwable {
  95             MethodHandle mh = lookup().findGetter(o.getClass(), "priv_field", int.class);
  96             int priv_field = (int) mh.invoke(o);
  97             priv_field = (int) mh.invokeExact(o);
  98             checkBadInvokeG(mh, this); // wrong nestmate
  99             checkBadInvokeG(mh, mh); // completely wrong type
 100 
 101             mh = lookup().findSetter(o.getClass(), "priv_field", int.class);
 102             mh.invoke(o, 2);
 103             mh.invokeExact(o, 3);
 104             checkBadInvokeS(mh, this); // wrong nestmate
 105             checkBadInvokeS(mh, mh); // completely wrong type
 106         }
 107         default void access_priv(InnerNested o) throws Throwable {
 108             MethodHandle mh = lookup().findGetter(o.getClass(), "priv_field", int.class);
 109             int priv_field = (int) mh.invoke(o);
 110             priv_field = (int) mh.invokeExact(o);
 111             checkBadInvokeG(mh, this); // wrong nestmate
 112             checkBadInvokeG(mh, mh); // completely wrong type
 113 
 114             mh = lookup().findSetter(o.getClass(), "priv_field", int.class);
 115             mh.invoke(o, 2);
 116             mh.invokeExact(o, 3);
 117             checkBadInvokeS(mh, this); // wrong nestmate
 118             checkBadInvokeS(mh, mh); // completely wrong type
 119         }
 120         default void access_priv(StaticNested o) throws Throwable {
 121             MethodHandle mh = lookup().findGetter(o.getClass(), "priv_field", int.class);
 122             int priv_field = (int) mh.invoke(o);
 123             priv_field = (int) mh.invokeExact(o);
 124             checkBadInvokeG(mh, this); // wrong nestmate
 125             checkBadInvokeG(mh, mh); // completely wrong type
 126 
 127             mh = lookup().findSetter(o.getClass(), "priv_field", int.class);
 128             mh.invoke(o, 2);
 129             mh.invokeExact(o, 3);
 130             checkBadInvokeS(mh, this); // wrong nestmate
 131             checkBadInvokeS(mh, mh); // completely wrong type
 132         }
 133     }
 134 
 135     static class StaticNested {
 136 
 137         private int priv_field;
 138 
 139         // public constructor so we aren't relying on private access
 140         public StaticNested() {}
 141 
 142         // Methods that will access private fields of nestmates
 143 
 144         void access_priv(TestMethodHandles o) throws Throwable {
 145             MethodHandle mh = lookup().findGetter(o.getClass(), "priv_field", int.class);
 146             this.priv_field = (int) mh.invoke(o);
 147             this.priv_field = (int) mh.invokeExact(o);
 148             checkBadInvokeG(mh, this); // wrong nestmate
 149             checkBadInvokeG(mh, mh); // completely wrong type
 150 
 151             mh = lookup().findSetter(o.getClass(), "priv_field", int.class);
 152             mh.invoke(o, 2);
 153             mh.invokeExact(o, 3);
 154             checkBadInvokeS(mh, this); // wrong nestmate
 155             checkBadInvokeS(mh, mh); // completely wrong type
 156         }
 157         void access_priv(InnerNested o) throws Throwable {
 158             MethodHandle mh = lookup().findGetter(o.getClass(), "priv_field", int.class);
 159             this.priv_field = (int) mh.invoke(o);
 160             this.priv_field = (int) mh.invokeExact(o);
 161             checkBadInvokeG(mh, this); // wrong nestmate
 162             checkBadInvokeG(mh, mh); // completely wrong type
 163 
 164             mh = lookup().findSetter(o.getClass(), "priv_field", int.class);
 165             mh.invoke(o, 2);
 166             mh.invokeExact(o, 3);
 167             checkBadInvokeS(mh, this); // wrong nestmate
 168             checkBadInvokeS(mh, mh); // completely wrong type
 169         }
 170         void access_priv(StaticNested o) throws Throwable {
 171             MethodHandle mh = lookup().findGetter(o.getClass(), "priv_field", int.class);
 172             this.priv_field = (int) mh.invoke(o);
 173             this.priv_field = (int) mh.invokeExact(o);
 174             checkBadInvokeG(mh, new TestMethodHandles()); // wrong nestmate
 175             checkBadInvokeG(mh, mh); // completely wrong type
 176 
 177             mh = lookup().findSetter(o.getClass(), "priv_field", int.class);
 178             mh.invoke(o, 2);
 179             mh.invokeExact(o, 3);
 180             checkBadInvokeS(mh, new TestMethodHandles()); // wrong nestmate
 181             checkBadInvokeS(mh, mh); // completely wrong type
 182         }
 183     }
 184 
 185     class InnerNested {
 186 
 187         private int priv_field;
 188 
 189         // public constructor so we aren't relying on private access
 190         public InnerNested() {}
 191 
 192         void access_priv(TestMethodHandles o) throws Throwable {
 193             MethodHandle mh = lookup().findGetter(o.getClass(), "priv_field", int.class);
 194             this.priv_field = (int) mh.invoke(o);
 195             this.priv_field = (int) mh.invokeExact(o);
 196             checkBadInvokeG(mh, this); // wrong nestmate
 197             checkBadInvokeG(mh, mh); // completely wrong type
 198 
 199             mh = lookup().findSetter(o.getClass(), "priv_field", int.class);
 200             mh.invoke(o, 2);
 201             mh.invokeExact(o, 3);
 202             checkBadInvokeS(mh, this); // wrong nestmate
 203             checkBadInvokeS(mh, mh); // completely wrong type
 204         }
 205         void access_priv(InnerNested o) throws Throwable {
 206             MethodHandle mh = lookup().findGetter(o.getClass(), "priv_field", int.class);
 207             this.priv_field = (int) mh.invoke(o);
 208             this.priv_field = (int) mh.invokeExact(o);
 209             checkBadInvokeG(mh, new StaticNested()); // wrong nestmate
 210             checkBadInvokeG(mh, mh); // completely wrong type
 211 
 212             mh = lookup().findSetter(o.getClass(), "priv_field", int.class);
 213             mh.invoke(o, 2);
 214             mh.invokeExact(o, 3);
 215             checkBadInvokeS(mh, new StaticNested()); // wrong nestmate
 216             checkBadInvokeS(mh, mh); // completely wrong type
 217         }
 218         void access_priv(StaticNested o) throws Throwable {
 219             MethodHandle mh = lookup().findGetter(o.getClass(), "priv_field", int.class);
 220             this.priv_field = (int) mh.invoke(o);
 221             this.priv_field = (int) mh.invokeExact(o);
 222             checkBadInvokeG(mh, this); // wrong nestmate
 223             checkBadInvokeG(mh, mh); // completely wrong type
 224 
 225             mh = lookup().findSetter(o.getClass(), "priv_field", int.class);
 226             mh.invoke(o, 2);
 227             mh.invokeExact(o, 3);
 228             checkBadInvokeS(mh, this); // wrong nestmate
 229             checkBadInvokeS(mh, mh); // completely wrong type
 230         }
 231     }
 232 
 233     static void checkBadInvokeG(MethodHandle mh, Object o) throws Throwable {
 234         try {
 235             int x = (int) mh.invoke(o);
 236             throw new Error("Invoke on MethodHandle " + mh + " with receiver "
 237                             + o + "should have failed with ClassCastException!");
 238         }
 239         catch (ClassCastException expected) {
 240             System.out.println("invoke got expected exception: " + expected);
 241         }
 242     }
 243 
 244     static void checkBadInvokeS(MethodHandle mh, Object o) throws Throwable {
 245         try {
 246             mh.invoke(o, 42);
 247             throw new Error("Invoke on MethodHandle " + mh + " with receiver "
 248                             + o + "should have failed with ClassCastException!");
 249          }
 250          catch (ClassCastException expected) {
 251              System.out.println("invoke got expected exception: " + expected);
 252          }
 253     }
 254 
 255     public static void main(String[] args) throws Throwable {
 256         TestMethodHandles o = new TestMethodHandles();
 257         StaticNested s = new StaticNested();
 258         InnerNested i = o.new InnerNested();
 259         StaticIface intf = new StaticIface() {};
 260 
 261         o.access_priv(new TestMethodHandles());
 262         o.access_priv(i);
 263         o.access_priv(s);
 264 
 265         s.access_priv(o);
 266         s.access_priv(i);
 267         s.access_priv(new StaticNested());
 268 
 269         i.access_priv(o);
 270         i.access_priv(o.new InnerNested());
 271         i.access_priv(s);
 272 
 273         intf.access_priv(o);
 274         intf.access_priv(i);
 275         intf.access_priv(s);
 276     }
 277 }