Skip to content

HiddenClassDefiner incorrectly assumes Unsafe.staticFieldBase(Field) returns a real Object #1672

Closed

Description

@breun

The combination of Google Guice 5.1.0 and the Azul Prime JVM is causing a VM crash. I've reached out to Azul support about this and they believe that the root cause is that the class com.google.inject.internal.aop.HiddenClassDefiner treats a klassOop as though it were an Object.

HiddenClassDefiner defines TRUSTED_LOOKUP_BASE like this:

private static final Object TRUSTED_LOOKUP_BASE;

And its value is obtained like this:

Method baseMethod = unsafeType.getMethod("staticFieldBase", Field.class);
TRUSTED_LOOKUP_BASE = baseMethod.invoke(THE_UNSAFE, trustedLookupField);

So TRUSTED_LOOKUP_BASE, nominally a private static final Object, is obtained by calling Unsafe.staticFieldBase() via reflection.

Here's how it's used in Guice:

public Class<?> define(Class<?> hostClass, byte[] bytecode) throws Exception {
    Lookup trustedLookup =
        (Lookup) GET_OBJECT_METHOD.invoke(THE_UNSAFE, TRUSTED_LOOKUP_BASE, TRUSTED_LOOKUP_OFFSET);

Which calls Unsafe.getObject((Object)TRUSTED_LOOKUP_BASE, (long)TRUSTED_LOOKUP_OFFSET).

This use of TRUSTED_LOOKUP_BASE ignores the admonitions of Unsafe.staticFieldBase(), which says the value is not guaranteed to be a real Object:

/**
 * Reports the location of a given static field, in conjunction with {@link
 * #staticFieldOffset}.
 * <p>Fetch the base "Object", if any, with which static fields of the
 * given class can be accessed via methods like {@link #getInt(Object,
 * long)}.  This value may be null.  This value may refer to an object
 * which is a "cookie", not guaranteed to be a real Object, and it should
 * not be used in any way except as argument to the get and put routines in
 * this class.
 */
@ForceInline
public Object staticFieldBase(Field f) {

Now, a lot of reflection code is generated on the fly at runtime and inlined. I'm also told the Prime VM emits a checkcast bytecode, which does what it says and checks the reference to be returned by getObject is, in fact, an Object, which a klassOop isn't. Hence the attempt to throw a ClassCastException in a place where the VM shouldn't.

Here is the hs_err file for the crash: hs_err_pid12.log.gz

Activity

  1. mcculls commented on Apr 5, 2023

    @mcculls
    Contributor

    Hi @breun - I'm not sure I fully agree with that assessment because the code is taking the values returned by staticFieldBase and staticFieldOffset and passing them into unsafe.getObject which is allowed (and intended) according to the Unsafe javadoc:

         * <li>The offset and object reference {@code o} (either null or
         * non-null) were both obtained via {@link #staticFieldOffset}
         * and {@link #staticFieldBase} (respectively) from the
         * reflective {@link Field} representation of some Java field.
    

    But I agree that we're not doing that directly though because of the use of the reflective call, and it appears that Azul Prime is doing something different when reflection is involved.

    I believe we can simplify that call to avoid using the value from staticFieldBase because we know that field is a member of Lookup.class - according to the javadoc we can use Lookup.class directly, which should hopefully avoid the issue on Azul Prime:

        Lookup trustedLookup =
            (Lookup) GET_OBJECT_METHOD.invoke(THE_UNSAFE, Lookup.class, TRUSTED_LOOKUP_OFFSET);
    

    I'll try to recreate the original issue to verify this fix.

  2. mcculls commented on Apr 7, 2023

    @mcculls
    Contributor

    @breun PR #1673 has a potential fix - could you build this locally and try it out with your Azul Prime setup?

  3. breun commented on Apr 11, 2023

    @breun
    Author

    @mcculls I've tried building your branch locally and I believe I need to use Bazel, which I've installed, but I haven't figured out yet what command I need to run to build Guice. Can you tell me how to build Guice or point me to documentation for this?

  4. mcculls commented on Apr 11, 2023

    @mcculls
    Contributor
  5. breun commented on Apr 12, 2023

    @breun
    Author

    I was able to install Guice 5.1.1-SNAPSHOT from your branch, but the next step is building Maven 3.9.1 with this version of Guice, but I various tests fail when building Maven 3.9.1 with Guice 5.1.1-SNAPSHOT due to java.lang.NoSuchMethodError: com.google.common.collect.ImmutableMap$Builder.buildOrThrow()Lcom/google/common/collect/ImmutableMap;. Any ideas? I can build Maven 3.9.1 with Guice 5.1.0 without problems.

  6. mcculls commented on Apr 12, 2023

    @mcculls
    Contributor
  7. added 2 commits that reference this issue on Apr 17, 2023
    37cd8ae
    3399615
  8. azul-jf commented on Apr 26, 2023

    @azul-jf

    Hi @mcculls we at Azul have a change for this issue which we prefer to the one you proposed. I believe we're waiting for Google to approve the paperwork we've submitted that's required to join the project. Is there someone who can help expedite the application?

  9. sameb commented on Apr 26, 2023

    @sameb
    Member

    @azul-jf: Please open a pull request with your proposed change and we can discuss it there. The automated CLA checks will kick in when the PR is open. It looks like Azul already has a corp CLA agreement AFAICT, so so long as the author of the PR is a member of Azul's CLA, it should just work.

  10. added 4 commits that reference this issue on May 4, 2023
    863ad8b
    95a2fbb
    d297c5b
    5a58425
  11. talios commented on Jul 5, 2025

    @talios

    Did this change ever get merged? I still see the warning with Maven 3.9.10, which uses the older 5.1.0, but I built a 3.9.11-SNAPSHOT using 6.0.0 of Guice, and the issues remain.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions

      ⌂ 换网址