1 /* 2 * Copyright (c) 2015, 2019, 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 package p1; 25 26 import java.lang.invoke.MethodHandle; 27 import java.lang.invoke.MethodHandles; 28 import java.lang.invoke.MethodHandles.Lookup; 29 import java.lang.invoke.MethodType; 30 31 import static java.lang.invoke.MethodHandles.Lookup.*; 32 33 import org.testng.annotations.BeforeTest; 34 import org.testng.annotations.Test; 35 import static org.testng.Assert.*; 36 37 /** 38 * Basic test case for module access checks and Lookup.in. 39 */ 40 41 @Test 42 public class Main { 43 44 private Class<?> p1_Type1; // m1, exported 45 private Class<?> p2_Type2; // m1, not exported 46 private Class<?> q1_Type1; // m2, exported 47 private Class<?> q2_Type2; // m2, not exported 48 private Class<?> signalClass; // java.base, not exported 49 private Class<?> unnamedClass; // class in unnamed module 50 51 @BeforeTest 52 public void setup() throws Exception { 53 try { 54 p1_Type1 = Class.forName("p1.Type1"); 55 p2_Type2 = Class.forName("p2.Type2"); 56 q1_Type1 = Class.forName("q1.Type1"); 57 q2_Type2 = Class.forName("q2.Type2"); 58 signalClass = Class.forName("jdk.internal.misc.Signal"); 59 unnamedClass = Class.forName("Unnamed"); 60 } catch (ClassNotFoundException e) { 61 throw new AssertionError(e); 62 } 63 64 // check setup 65 Module m1 = ModuleLayer.boot().findModule("m1").orElse(null); 66 assertNotNull(m1); 67 assertTrue(p1_Type1.getModule() == m1); 68 assertTrue(p2_Type2.getModule() == m1); 69 assertTrue(m1.isExported("p1")); 70 assertFalse(m1.isExported("p2")); 71 72 Module m2 = ModuleLayer.boot().findModule("m2").orElse(null); 73 assertNotNull(m2); 74 assertTrue(q1_Type1.getModule() == m2); 75 assertTrue(q2_Type2.getModule() == m2); 76 assertTrue(m2.isExported("q1")); 77 assertFalse(m2.isExported("q2")); 78 79 Module unnamedModule = unnamedClass.getModule(); 80 assertFalse(unnamedModule.isNamed()); 81 82 // m1 needs to read unnamed module 83 Main.class.getModule().addReads(unnamedModule); 84 } 85 86 /** 87 * MethodHandles.lookup() 88 * 89 * [A0] has module access 90 * [A1] can access all public types in m1 91 * [A2] can access public types in packages exported by modules that m1 reads 92 * [A3] cannot access public types in non-exported modules of modules that m1 reads 93 */ 94 public void testLookup() throws Exception { 95 Lookup lookup = MethodHandles.lookup(); 96 assertTrue((lookup.lookupModes() & MODULE) == MODULE); // [A0] 97 98 // m1 99 findConstructor(lookup, p1_Type1, void.class); // [A1] 100 findConstructor(lookup, p2_Type2, void.class); // [A1] 101 102 // m2 103 findConstructor(lookup, q1_Type1, void.class); // [A2] 104 findConstructorExpectingIAE(lookup, q2_Type2, void.class); // [A3] 105 106 // java.base 107 findConstructor(lookup, Object.class, void.class); // [A2] 108 findConstructorExpectingIAE(lookup, signalClass, void.class, String.class); // [A3] 109 110 // unnamed 111 findConstructor(lookup, unnamedClass, void.class); // [A3] 112 } 113 114 /** 115 * Hop to lookup class in the same module 116 * 117 * [A0] module and public access is not lost 118 */ 119 public void testToSameModule() throws Exception { 120 Lookup lookup = MethodHandles.lookup().in(p2_Type2); 121 assertTrue(lookup.lookupModes() == (MODULE|PUBLIC)); // [A0] 122 123 // m1 124 findConstructor(lookup, p1_Type1, void.class); 125 findConstructor(lookup, p2_Type2, void.class); 126 127 // m2 128 findConstructor(lookup, q1_Type1, void.class); 129 findConstructorExpectingIAE(lookup, q2_Type2, void.class); 130 131 // java.base 132 findConstructor(lookup, Object.class, void.class); 133 findConstructorExpectingIAE(lookup, signalClass, void.class, String.class); 134 135 // unnamed 136 findConstructor(lookup, unnamedClass, void.class); 137 } 138 139 /** 140 * Hop to lookup class in another named module 141 * 142 * [A0] has PUBLIC access if accessible; otherwise no access 143 * [A1] old lookup class becomes previous lookup class 144 */ 145 public void testFromNamedToNamedModule() throws Exception { 146 // m2/q1_Type1 is accessible to m1 whereas m2/q_Type2 is not accessible 147 Lookup lookup = MethodHandles.lookup().in(q1_Type1); 148 assertTrue(lookup.lookupModes() == PUBLIC); // [A0] 149 assertTrue(lookup.previousLookupClass() == Main.class); // [A1] 150 151 Lookup lookup2 = MethodHandles.lookup().in(q2_Type2); 152 assertTrue(lookup2.lookupModes() == 0); // [A0] 153 assertTrue(lookup2.previousLookupClass() == Main.class); // [A1] 154 155 // m1 156 findConstructorExpectingIAE(lookup, p1_Type1, void.class); 157 findConstructorExpectingIAE(lookup, p2_Type2, void.class); 158 159 findConstructorExpectingIAE(lookup2, p1_Type1, void.class); 160 findConstructorExpectingIAE(lookup2, p2_Type2, void.class); 161 162 // m2 163 findConstructor(lookup, q1_Type1, void.class); // m2/q1 is exported 164 findConstructorExpectingIAE(lookup, q2_Type2, void.class); 165 166 findConstructorExpectingIAE(lookup2, q1_Type1, void.class); 167 findConstructorExpectingIAE(lookup2, q2_Type2, void.class); 168 169 // java.base 170 findConstructor(lookup, Object.class, void.class); 171 findConstructorExpectingIAE(lookup, signalClass, void.class, String.class); 172 173 findConstructorExpectingIAE(lookup2, Object.class, void.class); 174 findConstructorExpectingIAE(lookup2, signalClass, void.class, String.class); 175 176 // unnamed 177 findConstructorExpectingIAE(lookup, unnamedClass, void.class); 178 179 findConstructorExpectingIAE(lookup2, unnamedClass, void.class); 180 181 } 182 183 /** 184 * Hop to lookup class in an unnamed module 185 * 186 * [A0] has PUBLIC access 187 */ 188 public void testFromNamedToUnnamedModule() throws Exception { 189 Lookup lookup = MethodHandles.lookup().in(unnamedClass); 190 assertTrue(lookup.lookupModes() == PUBLIC); // [A0] 191 192 // m1 193 findConstructor(lookup, p1_Type1, void.class); // p1 is exported 194 findConstructorExpectingIAE(lookup, p2_Type2, void.class); 195 196 // m2 197 findConstructor(lookup, q1_Type1, void.class); 198 findConstructorExpectingIAE(lookup, q2_Type2, void.class); 199 200 // java.base 201 findConstructor(lookup, Object.class, void.class); 202 findConstructorExpectingIAE(lookup, signalClass, void.class, String.class); 203 204 // unnamed 205 findConstructor(lookup, unnamedClass, void.class); 206 } 207 208 /** 209 * Hop from unnamed to named module. 210 * 211 * [A0] retains PUBLIC access 212 */ 213 public void testFromUnnamedToNamedModule() throws Exception { 214 Lookup lookup = MethodHandles.lookup(); 215 lookup = MethodHandles.privateLookupIn(unnamedClass, lookup).in(p1_Type1); 216 assertTrue(lookup.lookupModes() == PUBLIC); // A0 217 218 // m1 219 findConstructor(lookup, p1_Type1, void.class); 220 findConstructorExpectingIAE(lookup, p2_Type2, void.class); 221 222 // m2 223 findConstructor(lookup, q1_Type1, void.class); 224 findConstructorExpectingIAE(lookup, q2_Type2, void.class); 225 226 // java.base 227 findConstructor(lookup, Object.class, void.class); 228 findConstructorExpectingIAE(lookup, signalClass, void.class, String.class); 229 230 // unnamed 231 findConstructor(lookup, unnamedClass, void.class); 232 } 233 234 /** 235 * MethodHandles.publicLookup() 236 * 237 * [A0] has UNCONDITIONAL access 238 */ 239 public void testPublicLookup() throws Exception { 240 Lookup lookup = MethodHandles.publicLookup(); 241 assertTrue(lookup.lookupModes() == UNCONDITIONAL); // A0 242 243 // m1 244 findConstructor(lookup, p1_Type1, void.class); 245 findConstructorExpectingIAE(lookup, p2_Type2, void.class); 246 247 // m2 248 findConstructor(lookup, q1_Type1, void.class); 249 findConstructorExpectingIAE(lookup, q2_Type2, void.class); 250 251 // java.base 252 findConstructor(lookup, Object.class, void.class); 253 findConstructorExpectingIAE(lookup, signalClass, void.class, String.class); 254 255 // unnamed 256 findConstructor(lookup, unnamedClass, void.class); 257 } 258 259 /** 260 * Hop from publicLookup to accessible type in java.base 261 * 262 * [A0] has UNCONDITIONAL access 263 */ 264 public void testPublicLookupToBaseModule() throws Exception { 265 Lookup lookup = MethodHandles.publicLookup().in(String.class); 266 assertTrue(lookup.lookupModes() == UNCONDITIONAL); // A0 267 268 // m1 269 findConstructor(lookup, p1_Type1, void.class); 270 findConstructorExpectingIAE(lookup, p2_Type2, void.class); 271 272 // m2 273 findConstructor(lookup, q1_Type1, void.class); 274 findConstructorExpectingIAE(lookup, q2_Type2, void.class); 275 276 // java.base 277 findConstructor(lookup, Object.class, void.class); 278 findConstructorExpectingIAE(lookup, signalClass, void.class, String.class); 279 280 // unnamed 281 findConstructor(lookup, unnamedClass, void.class); 282 } 283 284 285 /** 286 * Hop from publicLookup to accessible type in named module. 287 * 288 * [A0] has UNCONDITIONAL access 289 */ 290 public void testPublicLookupToAccessibleTypeInNamedModule() throws Exception { 291 Lookup lookup = MethodHandles.publicLookup().in(p1_Type1); 292 assertTrue(lookup.lookupModes() == UNCONDITIONAL); // A0 293 294 // m1 295 findConstructor(lookup, p1_Type1, void.class); 296 findConstructorExpectingIAE(lookup, p2_Type2, void.class); 297 298 // m2 299 findConstructor(lookup, q1_Type1, void.class); 300 findConstructorExpectingIAE(lookup, q2_Type2, void.class); 301 302 // java.base 303 findConstructor(lookup, Object.class, void.class); 304 findConstructorExpectingIAE(lookup, signalClass, void.class, String.class); 305 306 // unnamed 307 findConstructor(lookup, unnamedClass, void.class); 308 } 309 310 /** 311 * Teleport from publicLookup to inaccessible type in named module. 312 * 313 * [A0] has no access 314 */ 315 public void testPublicLookupToInaccessibleTypeInNamedModule() throws Exception { 316 Lookup lookup = MethodHandles.publicLookup().in(p2_Type2); 317 assertTrue(lookup.lookupModes() == 0); // A0 318 319 // m1 320 findConstructorExpectingIAE(lookup, p1_Type1, void.class); 321 findConstructorExpectingIAE(lookup, p2_Type2, void.class); 322 323 // m2 324 findConstructorExpectingIAE(lookup, q1_Type1, void.class); 325 findConstructorExpectingIAE(lookup, q2_Type2, void.class); 326 327 // java.base 328 findConstructorExpectingIAE(lookup, Object.class, void.class); 329 findConstructorExpectingIAE(lookup, signalClass, void.class, String.class); 330 331 // unnamed 332 findConstructorExpectingIAE(lookup, unnamedClass, void.class); 333 } 334 335 /** 336 * Teleport from publicLookup to public type in unnamed module 337 * 338 * [A0] has UNCONDITIONAL access 339 */ 340 public void testPublicLookupToUnnamedModule() throws Exception { 341 Lookup lookup = MethodHandles.publicLookup().in(unnamedClass); 342 assertTrue(lookup.lookupModes() == UNCONDITIONAL); // A0 343 344 // m1 345 findConstructor(lookup, p1_Type1, void.class); 346 findConstructorExpectingIAE(lookup, p2_Type2, void.class); 347 348 // m2 349 findConstructor(lookup, q1_Type1, void.class); 350 findConstructorExpectingIAE(lookup, q2_Type2, void.class); 351 352 // java.base 353 findConstructor(lookup, Object.class, void.class); 354 findConstructorExpectingIAE(lookup, signalClass, void.class, String.class); 355 356 // unnamed 357 findConstructor(lookup, unnamedClass, void.class); 358 } 359 360 /** 361 * Invokes Lookup findConstructor with a method type constructored from the 362 * given return and parameter types, expecting IllegalAccessException to be 363 * thrown. 364 */ 365 static void findConstructorExpectingIAE(Lookup lookup, 366 Class<?> clazz, 367 Class<?> rtype, 368 Class<?>... ptypes) throws Exception { 369 try { 370 findConstructor(lookup, clazz, rtype, ptypes); 371 assertTrue(false); 372 } catch (IllegalAccessException expected) { } 373 } 374 375 /** 376 * Invokes Lookup findConstructor with a method type constructored from the 377 * given return and parameter types. 378 */ 379 static MethodHandle findConstructor(Lookup lookup, 380 Class<?> clazz, 381 Class<?> rtype, 382 Class<?>... ptypes) throws Exception { 383 MethodType mt = MethodType.methodType(rtype, ptypes); 384 return lookup.findConstructor(clazz, mt); 385 } 386 }