diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3ba4f4faea..d9cd933db8 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -2,7 +2,7 @@ # For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-maven name: continuous-integration env: - USE_BAZEL_VERSION: '4.2.2' + USE_BAZEL_VERSION: '6.1.2' USE_JAVA_DISTRIBUTION: 'zulu' USE_JAVA_VERSION: '11' diff --git a/core/src/com/google/inject/internal/aop/AnonymousClassDefiner.java b/core/src/com/google/inject/internal/aop/AnonymousClassDefiner.java index 87c47a6ba6..e26d20ea41 100644 --- a/core/src/com/google/inject/internal/aop/AnonymousClassDefiner.java +++ b/core/src/com/google/inject/internal/aop/AnonymousClassDefiner.java @@ -16,7 +16,6 @@ package com.google.inject.internal.aop; -import java.lang.reflect.Field; import java.lang.reflect.Method; /** @@ -26,17 +25,16 @@ */ final class AnonymousClassDefiner implements ClassDefiner { - private static final Object THE_UNSAFE; + private static final sun.misc.Unsafe THE_UNSAFE; private static final Method ANONYMOUS_DEFINE_METHOD; static { try { - Class unsafeType = Class.forName("sun.misc.Unsafe"); - Field theUnsafeField = unsafeType.getDeclaredField("theUnsafe"); - theUnsafeField.setAccessible(true); - THE_UNSAFE = theUnsafeField.get(null); + THE_UNSAFE = UnsafeGetter.getUnsafe(); + // defineAnonymousClass was removed in JDK17, so we must refer to it reflectively. ANONYMOUS_DEFINE_METHOD = - unsafeType.getMethod("defineAnonymousClass", Class.class, byte[].class, Object[].class); + sun.misc.Unsafe.class.getMethod( + "defineAnonymousClass", Class.class, byte[].class, Object[].class); } catch (ReflectiveOperationException e) { throw new ExceptionInInitializerError(e); } diff --git a/core/src/com/google/inject/internal/aop/HiddenClassDefiner.java b/core/src/com/google/inject/internal/aop/HiddenClassDefiner.java index af36f7be0c..1486cb8c93 100644 --- a/core/src/com/google/inject/internal/aop/HiddenClassDefiner.java +++ b/core/src/com/google/inject/internal/aop/HiddenClassDefiner.java @@ -28,22 +28,18 @@ */ final class HiddenClassDefiner implements ClassDefiner { - private static final Object THE_UNSAFE; - private static final Object TRUSTED_LOOKUP_OFFSET; - private static final Method GET_OBJECT_METHOD; + private static final sun.misc.Unsafe THE_UNSAFE; + private static final Object TRUSTED_LOOKUP_BASE; + private static final long TRUSTED_LOOKUP_OFFSET; private static final Object HIDDEN_CLASS_OPTIONS; private static final Method HIDDEN_DEFINE_METHOD; static { try { - Class unsafeType = Class.forName("sun.misc.Unsafe"); - Field theUnsafeField = unsafeType.getDeclaredField("theUnsafe"); - theUnsafeField.setAccessible(true); - THE_UNSAFE = theUnsafeField.get(null); + THE_UNSAFE = UnsafeGetter.getUnsafe(); Field trustedLookupField = Lookup.class.getDeclaredField("IMPL_LOOKUP"); - Method offsetMethod = unsafeType.getMethod("staticFieldOffset", Field.class); - TRUSTED_LOOKUP_OFFSET = offsetMethod.invoke(THE_UNSAFE, trustedLookupField); - GET_OBJECT_METHOD = unsafeType.getMethod("getObject", Object.class, long.class); + TRUSTED_LOOKUP_BASE = THE_UNSAFE.staticFieldBase(trustedLookupField); + TRUSTED_LOOKUP_OFFSET = THE_UNSAFE.staticFieldOffset(trustedLookupField); HIDDEN_CLASS_OPTIONS = classOptions("NESTMATE"); HIDDEN_DEFINE_METHOD = Lookup.class.getMethod( @@ -56,7 +52,7 @@ final class HiddenClassDefiner implements ClassDefiner { @Override public Class define(Class hostClass, byte[] bytecode) throws Exception { Lookup trustedLookup = - (Lookup) GET_OBJECT_METHOD.invoke(THE_UNSAFE, Lookup.class, TRUSTED_LOOKUP_OFFSET); + (Lookup) THE_UNSAFE.getObject(TRUSTED_LOOKUP_BASE, TRUSTED_LOOKUP_OFFSET); Lookup definedLookup = (Lookup) HIDDEN_DEFINE_METHOD.invoke( diff --git a/core/src/com/google/inject/internal/aop/UnsafeGetter.java b/core/src/com/google/inject/internal/aop/UnsafeGetter.java new file mode 100644 index 0000000000..c7221b658f --- /dev/null +++ b/core/src/com/google/inject/internal/aop/UnsafeGetter.java @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2023 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.inject.internal.aop; + +final class UnsafeGetter { + + private UnsafeGetter() {} + + static sun.misc.Unsafe getUnsafe() throws ReflectiveOperationException { + try { + return sun.misc.Unsafe.getUnsafe(); + } catch (SecurityException unusedFallbackToReflection) { + } + // Note that we do not do this in a privileged action because we expect we're already in a + // privileged block (from UnsafeClassDefiner). + Class k = sun.misc.Unsafe.class; + for (java.lang.reflect.Field f : k.getDeclaredFields()) { + f.setAccessible(true); + Object x = f.get(null); + if (k.isInstance(x)) { + return k.cast(x); + } + } + throw new NoSuchFieldError("the Unsafe"); + } +}