From 2b37f020862e45be58f246a63c2f97fdaff0d433 Mon Sep 17 00:00:00 2001 From: Guice Team Date: Fri, 10 May 2024 10:56:03 -0700 Subject: [PATCH] Allow AnonymousClassDefiner class initializer complete normally if running on JDK >=17 with Unsafe.defineAnonymousClass removed. PiperOrigin-RevId: 632544907 --- .../internal/aop/AnonymousClassDefiner.java | 22 ++++++++++++++++--- .../internal/aop/UnsafeClassDefiner.java | 3 ++- 2 files changed, 21 insertions(+), 4 deletions(-) diff --git a/core/src/com/google/inject/internal/aop/AnonymousClassDefiner.java b/core/src/com/google/inject/internal/aop/AnonymousClassDefiner.java index e26d20ea41..ec43a6c3d3 100644 --- a/core/src/com/google/inject/internal/aop/AnonymousClassDefiner.java +++ b/core/src/com/google/inject/internal/aop/AnonymousClassDefiner.java @@ -28,20 +28,36 @@ final class AnonymousClassDefiner implements ClassDefiner { private static final sun.misc.Unsafe THE_UNSAFE; private static final Method ANONYMOUS_DEFINE_METHOD; + /** True if this class err'd during initialization and should not be used. */ + static final boolean HAS_ERROR; + static { + sun.misc.Unsafe theUnsafe; + Method anonymousDefineMethod; try { - THE_UNSAFE = UnsafeGetter.getUnsafe(); + theUnsafe = UnsafeGetter.getUnsafe(); // defineAnonymousClass was removed in JDK17, so we must refer to it reflectively. - ANONYMOUS_DEFINE_METHOD = + anonymousDefineMethod = sun.misc.Unsafe.class.getMethod( "defineAnonymousClass", Class.class, byte[].class, Object[].class); } catch (ReflectiveOperationException e) { - throw new ExceptionInInitializerError(e); + theUnsafe = null; + anonymousDefineMethod = null; } + + THE_UNSAFE = theUnsafe; + ANONYMOUS_DEFINE_METHOD = anonymousDefineMethod; + HAS_ERROR = theUnsafe == null; } @Override public Class define(Class hostClass, byte[] bytecode) throws Exception { + if (HAS_ERROR) { + throw new IllegalStateException( + "Should not be called. An earlier error occurred during AnonymousClassDefiner static" + + " initialization."); + } + return (Class) ANONYMOUS_DEFINE_METHOD.invoke(THE_UNSAFE, hostClass, bytecode, null); } } diff --git a/core/src/com/google/inject/internal/aop/UnsafeClassDefiner.java b/core/src/com/google/inject/internal/aop/UnsafeClassDefiner.java index 6391ae3194..d3540d28f0 100644 --- a/core/src/com/google/inject/internal/aop/UnsafeClassDefiner.java +++ b/core/src/com/google/inject/internal/aop/UnsafeClassDefiner.java @@ -58,7 +58,8 @@ final class UnsafeClassDefiner implements ClassDefiner { static { ClassDefiner unsafeDefiner = tryPrivileged(AnonymousClassDefiner::new, "Cannot bind Unsafe.defineAnonymousClass"); - if (unsafeDefiner == null) { + + if (AnonymousClassDefiner.HAS_ERROR || unsafeDefiner == null) { unsafeDefiner = tryPrivileged( HiddenClassDefiner::new, "Cannot bind MethodHandles.Lookup.defineHiddenClass");