268 Lookup lookup = lookup().dropLookupMode(Lookup.PRIVATE); 269 byte[] bytes = Files.readAllBytes(CLASSES_DIR.resolve("HiddenClass.class")); 270 lookup.defineHiddenClass(bytes, false); 271 } 272 273 @DataProvider(name = "nestedTypesOrAnonymousClass") 274 private Object[][] nestedTypesOrAnonymousClass() { 275 return new Object[][] { 276 // class file with bad InnerClasses or EnclosingMethod attribute 277 new Object[] { "Outer", null }, 278 new Object[] { "Outer$Inner", "Outer" }, 279 new Object[] { "EnclosingClass", null }, 280 new Object[] { "EnclosingClass$1", "EnclosingClass" }, 281 }; 282 } 283 284 @Test(dataProvider = "nestedTypesOrAnonymousClass") 285 public void hasInnerClassesOrEnclosingMethodAttribute(String className, String badDeclaringClassName) throws Throwable { 286 byte[] bytes = Files.readAllBytes(CLASSES_10_DIR.resolve(className + ".class")); 287 Class<?> hc = lookup().defineHiddenClass(bytes, false).lookupClass(); 288 hiddenClassWithBadAttribute(hc, badDeclaringClassName, null); 289 } 290 291 private static final String BAD_NEST_HOST_CLASS_ERROR = "Unable to load nest-host class (Outer) of Outer$Inner/"; 292 293 // define a hidden class with static nest membership 294 // it fails when it attempts to validate the nest membership 295 @Test 296 public void hasStaticNestHost() throws Exception { 297 byte[] bytes = Files.readAllBytes(CLASSES_DIR.resolve("Outer$Inner.class")); 298 Class<?> hc = lookup().defineHiddenClass(bytes, false).lookupClass(); 299 hiddenClassWithBadAttribute(hc, "Outer", BAD_NEST_HOST_CLASS_ERROR); 300 } 301 302 @Test 303 public void hasStaticNestMembers() throws Throwable { 304 byte[] bytes = Files.readAllBytes(CLASSES_DIR.resolve("Outer.class")); 305 Class<?> hc = lookup().defineHiddenClass(bytes, false).lookupClass(); 306 assertHiddenClass(hc); 307 assertTrue(hc.getNestHost() == hc); 308 try { 309 // fail to validate the static nest membership 310 hc.getNestMembers(); 311 assertTrue(false); 312 } catch (NoClassDefFoundError e) { 313 if (!e.getMessage().equals("Outer$Inner")) { 314 throw e; 315 } 316 } 317 } 318 319 // a hidden class with bad InnerClasses or EnclosingMethod attribute 320 private void hiddenClassWithBadAttribute(Class<?> hc, String badDeclaringClassName, String badNestMembersError) { 321 assertTrue(hc.isHiddenClass()); 322 assertTrue(hc.getCanonicalName() == null); 323 assertTrue(hc.getName().contains("/")); 324 325 if (badDeclaringClassName == null) { 326 // the following reflection API assumes a good name in InnerClasses 327 // or EnclosingMethod attribute can successfully be resolved. 328 assertTrue(hc.getSimpleName().length() > 0); 329 assertFalse(hc.isAnonymousClass()); 330 assertFalse(hc.isLocalClass()); 331 assertFalse(hc.isMemberClass()); 332 } else { 333 declaringClassNotFound(hc, badDeclaringClassName); 334 } 335 336 // validation of nest membership may fail 337 assertTrue(hc.getNestHost() == hc); 338 try { 339 // validate the static nest membership 340 hc.getNestMembers(); 341 assertTrue(badNestMembersError == null); 342 } catch (NoClassDefFoundError e) { 343 if (!e.getMessage().startsWith(badNestMembersError)) { 344 throw e; 345 } 346 } 347 } 348 349 // Class::getSimpleName, Class::isMemberClass 350 private void declaringClassNotFound(Class<?> c, String cn) { 351 try { 352 // fail to find declaring/enclosing class 353 c.isMemberClass(); 354 assertTrue(false); 355 } catch (NoClassDefFoundError e) { 356 if (!e.getMessage().equals(cn)) { 357 throw e; 358 } 359 } 360 try { 361 // fail to find declaring/enclosing class 362 c.getSimpleName(); 363 assertTrue(false); 364 } catch (NoClassDefFoundError e) { 365 if (!e.getMessage().equals(cn)) { 366 throw e; | 268 Lookup lookup = lookup().dropLookupMode(Lookup.PRIVATE); 269 byte[] bytes = Files.readAllBytes(CLASSES_DIR.resolve("HiddenClass.class")); 270 lookup.defineHiddenClass(bytes, false); 271 } 272 273 @DataProvider(name = "nestedTypesOrAnonymousClass") 274 private Object[][] nestedTypesOrAnonymousClass() { 275 return new Object[][] { 276 // class file with bad InnerClasses or EnclosingMethod attribute 277 new Object[] { "Outer", null }, 278 new Object[] { "Outer$Inner", "Outer" }, 279 new Object[] { "EnclosingClass", null }, 280 new Object[] { "EnclosingClass$1", "EnclosingClass" }, 281 }; 282 } 283 284 @Test(dataProvider = "nestedTypesOrAnonymousClass") 285 public void hasInnerClassesOrEnclosingMethodAttribute(String className, String badDeclaringClassName) throws Throwable { 286 byte[] bytes = Files.readAllBytes(CLASSES_10_DIR.resolve(className + ".class")); 287 Class<?> hc = lookup().defineHiddenClass(bytes, false).lookupClass(); 288 hiddenClassWithBadAttribute(hc, badDeclaringClassName); 289 } 290 291 // define a hidden class with static nest membership 292 @Test 293 public void hasStaticNestHost() throws Exception { 294 byte[] bytes = Files.readAllBytes(CLASSES_DIR.resolve("Outer$Inner.class")); 295 Class<?> hc = lookup().defineHiddenClass(bytes, false).lookupClass(); 296 hiddenClassWithBadAttribute(hc, "Outer"); 297 } 298 299 @Test 300 public void hasStaticNestMembers() throws Throwable { 301 byte[] bytes = Files.readAllBytes(CLASSES_DIR.resolve("Outer.class")); 302 Class<?> hc = lookup().defineHiddenClass(bytes, false).lookupClass(); 303 assertHiddenClass(hc); 304 assertTrue(hc.getNestHost() == hc); 305 Class<?>[] members = hc.getNestMembers(); 306 assertTrue(members.length == 1 && members[0] == hc); 307 } 308 309 // a hidden class with bad InnerClasses or EnclosingMethod attribute 310 private void hiddenClassWithBadAttribute(Class<?> hc, String badDeclaringClassName) { 311 assertTrue(hc.isHiddenClass()); 312 assertTrue(hc.getCanonicalName() == null); 313 assertTrue(hc.getName().contains("/")); 314 315 if (badDeclaringClassName == null) { 316 // the following reflection API assumes a good name in InnerClasses 317 // or EnclosingMethod attribute can successfully be resolved. 318 assertTrue(hc.getSimpleName().length() > 0); 319 assertFalse(hc.isAnonymousClass()); 320 assertFalse(hc.isLocalClass()); 321 assertFalse(hc.isMemberClass()); 322 } else { 323 declaringClassNotFound(hc, badDeclaringClassName); 324 } 325 326 // validation of nest membership 327 assertTrue(hc.getNestHost() == hc); 328 // validate the static nest membership 329 Class<?>[] members = hc.getNestMembers(); 330 assertTrue(members.length == 1 && members[0] == hc); 331 } 332 333 // Class::getSimpleName, Class::isMemberClass 334 private void declaringClassNotFound(Class<?> c, String cn) { 335 try { 336 // fail to find declaring/enclosing class 337 c.isMemberClass(); 338 assertTrue(false); 339 } catch (NoClassDefFoundError e) { 340 if (!e.getMessage().equals(cn)) { 341 throw e; 342 } 343 } 344 try { 345 // fail to find declaring/enclosing class 346 c.getSimpleName(); 347 assertTrue(false); 348 } catch (NoClassDefFoundError e) { 349 if (!e.getMessage().equals(cn)) { 350 throw e; |