Skip to content

Commit

Permalink
If there is an error during HiddenClassDefiner class initialization, …
Browse files Browse the repository at this point in the history
…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: 631862800
  • Loading branch information
java-team-github-bot authored and Guice Team committed May 8, 2024
1 parent e67faa9 commit 42fbaf5
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 8 deletions.
43 changes: 35 additions & 8 deletions core/src/com/google/inject/internal/aop/HiddenClassDefiner.java
Original file line number Diff line number Diff line change
Expand Up @@ -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 =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down

0 comments on commit 42fbaf5

Please sign in to comment.