From 19194a3d8c42afb1fd7bd1404a9c6ae2f66677c1 Mon Sep 17 00:00:00 2001 From: Guice Team Date: Mon, 6 May 2024 11:12:40 -0700 Subject: [PATCH] If there is an error during HiddenClassDefiner class initialization, record the state in a public boolean field. Change UnsafeClassDefiner to check HiddenClassDefiner state and set UNSAFE_DEFINER as null if there's an error. An IllegalStateException is thrown if HiddenClassDefiner.define() is called in that case. PiperOrigin-RevId: 631124059 --- .../internal/aop/HiddenClassDefiner.java | 43 +++++++++++++++---- .../internal/aop/UnsafeClassDefiner.java | 3 ++ 2 files changed, 38 insertions(+), 8 deletions(-) diff --git a/core/src/com/google/inject/internal/aop/HiddenClassDefiner.java b/core/src/com/google/inject/internal/aop/HiddenClassDefiner.java index 1486cb8c93..8fb2a900c5 100644 --- a/core/src/com/google/inject/internal/aop/HiddenClassDefiner.java +++ b/core/src/com/google/inject/internal/aop/HiddenClassDefiner.java @@ -34,23 +34,50 @@ final class HiddenClassDefiner implements ClassDefiner { private static final Object HIDDEN_CLASS_OPTIONS; private static final Method HIDDEN_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; + Object trustedLookupBase; + long trustedLookupOffset; + Object hiddenClassOptions; + Method hiddenDefineMethod; try { - THE_UNSAFE = UnsafeGetter.getUnsafe(); + theUnsafe = UnsafeGetter.getUnsafe(); Field trustedLookupField = Lookup.class.getDeclaredField("IMPL_LOOKUP"); - TRUSTED_LOOKUP_BASE = THE_UNSAFE.staticFieldBase(trustedLookupField); - TRUSTED_LOOKUP_OFFSET = THE_UNSAFE.staticFieldOffset(trustedLookupField); - HIDDEN_CLASS_OPTIONS = classOptions("NESTMATE"); - HIDDEN_DEFINE_METHOD = + trustedLookupBase = theUnsafe.staticFieldBase(trustedLookupField); + trustedLookupOffset = theUnsafe.staticFieldOffset(trustedLookupField); + hiddenClassOptions = classOptions("NESTMATE"); + hiddenDefineMethod = Lookup.class.getMethod( - "defineHiddenClass", byte[].class, boolean.class, HIDDEN_CLASS_OPTIONS.getClass()); - } catch (ReflectiveOperationException e) { - throw new ExceptionInInitializerError(e); + "defineHiddenClass", byte[].class, boolean.class, hiddenClassOptions.getClass()); + } catch (Throwable e) { + // Allow the static initialization to complete without + // throwing an exception. + theUnsafe = null; + trustedLookupBase = null; + trustedLookupOffset = 0; + hiddenClassOptions = null; + hiddenDefineMethod = null; } + + THE_UNSAFE = theUnsafe; + TRUSTED_LOOKUP_BASE = trustedLookupBase; + TRUSTED_LOOKUP_OFFSET = trustedLookupOffset; + HIDDEN_CLASS_OPTIONS = hiddenClassOptions; + HIDDEN_DEFINE_METHOD = hiddenDefineMethod; + 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 HiddenClassDefiner static" + + " initialization."); + } + Lookup trustedLookup = (Lookup) THE_UNSAFE.getObject(TRUSTED_LOOKUP_BASE, TRUSTED_LOOKUP_OFFSET); Lookup definedLookup = diff --git a/core/src/com/google/inject/internal/aop/UnsafeClassDefiner.java b/core/src/com/google/inject/internal/aop/UnsafeClassDefiner.java index 68b2374616..6391ae3194 100644 --- a/core/src/com/google/inject/internal/aop/UnsafeClassDefiner.java +++ b/core/src/com/google/inject/internal/aop/UnsafeClassDefiner.java @@ -62,6 +62,9 @@ final class UnsafeClassDefiner implements ClassDefiner { unsafeDefiner = tryPrivileged( HiddenClassDefiner::new, "Cannot bind MethodHandles.Lookup.defineHiddenClass"); + if (HiddenClassDefiner.HAS_ERROR) { + unsafeDefiner = null; + } } UNSAFE_DEFINER = unsafeDefiner; }