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