@@ -491,7 +491,10 @@ public static Class defineClass(String className, byte[] b, ClassLoader loader,
491
491
ProtectionDomain protectionDomain , Class <?> contextClass ) throws Exception {
492
492
493
493
Class c = null ;
494
- if (contextClass != null && privateLookupInMethod != null && lookupDefineClassMethod != null ) {
494
+
495
+ // Preferred option: JDK 9+ Lookup.defineClass API if ClassLoader matches
496
+ if (contextClass != null && contextClass .getClassLoader () == loader &&
497
+ privateLookupInMethod != null && lookupDefineClassMethod != null ) {
495
498
try {
496
499
MethodHandles .Lookup lookup = (MethodHandles .Lookup )
497
500
privateLookupInMethod .invoke (null , contextClass , MethodHandles .lookup ());
@@ -510,29 +513,52 @@ public static Class defineClass(String className, byte[] b, ClassLoader loader,
510
513
throw new CodeGenerationException (ex );
511
514
}
512
515
}
513
- if (protectionDomain == null ) {
514
- protectionDomain = PROTECTION_DOMAIN ;
515
- }
516
- if (c == null ) {
517
- if (classLoaderDefineClassMethod != null ) {
518
- Object [] args = new Object []{className , b , 0 , b .length , protectionDomain };
519
- try {
520
- if (!classLoaderDefineClassMethod .isAccessible ()) {
521
- classLoaderDefineClassMethod .setAccessible (true );
522
- }
523
- c = (Class ) classLoaderDefineClassMethod .invoke (loader , args );
524
- }
525
- catch (InvocationTargetException ex ) {
526
- throw new CodeGenerationException (ex .getTargetException ());
516
+
517
+ // Classic option: protected ClassLoader.defineClass method
518
+ if (c == null && classLoaderDefineClassMethod != null ) {
519
+ if (protectionDomain == null ) {
520
+ protectionDomain = PROTECTION_DOMAIN ;
521
+ }
522
+ Object [] args = new Object []{className , b , 0 , b .length , protectionDomain };
523
+ try {
524
+ if (!classLoaderDefineClassMethod .isAccessible ()) {
525
+ classLoaderDefineClassMethod .setAccessible (true );
527
526
}
528
- catch (Throwable ex ) {
527
+ c = (Class ) classLoaderDefineClassMethod .invoke (loader , args );
528
+ }
529
+ catch (InvocationTargetException ex ) {
530
+ throw new CodeGenerationException (ex .getTargetException ());
531
+ }
532
+ catch (Throwable ex ) {
533
+ // Fall through if setAccessible fails with InaccessibleObjectException on JDK 9+
534
+ // (on the module path and/or with a JVM bootstrapped with --illegal-access=deny)
535
+ if (!ex .getClass ().getName ().endsWith ("InaccessibleObjectException" )) {
529
536
throw new CodeGenerationException (ex );
530
537
}
531
538
}
532
- else {
533
- throw new CodeGenerationException (THROWABLE );
539
+ }
540
+
541
+ // Fallback option: JDK 9+ Lookup.defineClass API even if ClassLoader does not match
542
+ if (c == null && contextClass != null && contextClass .getClassLoader () != loader &&
543
+ privateLookupInMethod != null && lookupDefineClassMethod != null ) {
544
+ try {
545
+ MethodHandles .Lookup lookup = (MethodHandles .Lookup )
546
+ privateLookupInMethod .invoke (null , contextClass , MethodHandles .lookup ());
547
+ c = (Class ) lookupDefineClassMethod .invoke (lookup , b );
548
+ }
549
+ catch (InvocationTargetException ex ) {
550
+ throw new CodeGenerationException (ex .getTargetException ());
551
+ }
552
+ catch (Throwable ex ) {
553
+ throw new CodeGenerationException (ex );
534
554
}
535
555
}
556
+
557
+ // No defineClass variant available at all?
558
+ if (c == null ) {
559
+ throw new CodeGenerationException (THROWABLE );
560
+ }
561
+
536
562
// Force static initializers to run.
537
563
Class .forName (className , true , loader );
538
564
return c ;
0 commit comments