diff --git a/core/src/com/google/inject/internal/InternalFlags.java b/core/src/com/google/inject/internal/InternalFlags.java index ebaf26eeaa..e6034406f8 100644 --- a/core/src/com/google/inject/internal/InternalFlags.java +++ b/core/src/com/google/inject/internal/InternalFlags.java @@ -69,13 +69,6 @@ public enum CustomClassLoadingOption { */ OFF, - /** - * Define fast/enhanced types anonymously as hidden nest-mates, never creates class loaders. - * This is faster than regular class loading and the resulting classes are easier to unload. - * - *

Note: with this option you cannot look up fast/enhanced types by name or mock/spy them. - */ - ANONYMOUS, /** * Attempt to define fast/enhanced types in the same class loader as their original type. diff --git a/core/src/com/google/inject/internal/aop/AnonymousClassDefiner.java b/core/src/com/google/inject/internal/aop/AnonymousClassDefiner.java deleted file mode 100644 index cc9fe49267..0000000000 --- a/core/src/com/google/inject/internal/aop/AnonymousClassDefiner.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright (C) 2021 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; - -import java.lang.reflect.Method; - -/** - * {@link ClassDefiner} that defines classes using {@code sun.misc.Unsafe#defineAnonymousClass}. - * - * @author mcculls@gmail.com (Stuart McCulloch) - */ -@SuppressWarnings("SunApi") -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 { - theUnsafe = UnsafeGetter.getUnsafe(); - // defineAnonymousClass was removed in JDK17, so we must refer to it reflectively. - anonymousDefineMethod = - sun.misc.Unsafe.class.getMethod( - "defineAnonymousClass", Class.class, byte[].class, Object[].class); - } catch (ReflectiveOperationException 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/ClassDefining.java b/core/src/com/google/inject/internal/aop/ClassDefining.java index b8f276fb9b..f5f5cc553a 100644 --- a/core/src/com/google/inject/internal/aop/ClassDefining.java +++ b/core/src/com/google/inject/internal/aop/ClassDefining.java @@ -36,7 +36,7 @@ private ClassDefining() {} // initialization-on-demand... private static class ClassDefinerHolder { static final ClassDefiner INSTANCE = bindClassDefiner(); - static final boolean IS_UNSAFE = INSTANCE instanceof UnsafeClassDefiner; + static final boolean IS_UNSAFE = INSTANCE instanceof LookupClassDefiner; } /** Defines a new class relative to the host. */ @@ -51,12 +51,7 @@ public static boolean hasPackageAccess() { /** Returns true if it's possible to load by name proxies defined from the given host. */ public static boolean canLoadProxyByName(Class hostClass) { - return !ClassDefinerHolder.IS_UNSAFE || UnsafeClassDefiner.canLoadProxyByName(hostClass); - } - - /** Returns true if it's possible to downcast to proxies defined from the given host. */ - public static boolean canDowncastToProxy(Class hostClass) { - return !ClassDefinerHolder.IS_UNSAFE || UnsafeClassDefiner.canDowncastToProxy(hostClass); + return !ClassDefinerHolder.IS_UNSAFE || LookupClassDefiner.canLoadProxyByName(hostClass); } /** Binds the preferred {@link ClassDefiner} instance. */ @@ -65,8 +60,8 @@ static ClassDefiner bindClassDefiner() { CustomClassLoadingOption loadingOption = InternalFlags.getCustomClassLoadingOption(); if (loadingOption == CustomClassLoadingOption.CHILD) { return new ChildClassDefiner(); // override default choice - } else if (UnsafeClassDefiner.isAccessible()) { - return new UnsafeClassDefiner(); // default choice if available + } else if (LookupClassDefiner.isAccessible()) { + return new LookupClassDefiner(); // default choice if available } else if (loadingOption != CustomClassLoadingOption.OFF) { return new ChildClassDefiner(); // second choice unless forbidden } else { diff --git a/core/src/com/google/inject/internal/aop/Enhancer.java b/core/src/com/google/inject/internal/aop/Enhancer.java index c3bc63c26d..6380da2a2c 100644 --- a/core/src/com/google/inject/internal/aop/Enhancer.java +++ b/core/src/com/google/inject/internal/aop/Enhancer.java @@ -167,8 +167,8 @@ final class Enhancer extends AbstractGlueGenerator { super(hostClass, ENHANCER_BY_GUICE_MARKER); this.bridgeDelegates = bridgeDelegates; - // with defineAnonymousClass we can't downcast to the proxy and must use host instead - this.checkcastToProxy = ClassDefining.canDowncastToProxy(hostClass) ? proxyName : hostName; + // Generated code can downcast to the generated proxy type. + this.checkcastToProxy = proxyName; } @Override diff --git a/core/src/com/google/inject/internal/aop/HiddenClassDefiner.java b/core/src/com/google/inject/internal/aop/HiddenClassDefiner.java index a63ec59533..3420691c44 100644 --- a/core/src/com/google/inject/internal/aop/HiddenClassDefiner.java +++ b/core/src/com/google/inject/internal/aop/HiddenClassDefiner.java @@ -16,87 +16,75 @@ package com.google.inject.internal.aop; +import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodHandles.Lookup; -import java.lang.reflect.Array; -import java.lang.reflect.Field; import java.lang.reflect.Method; - /** * {@link ClassDefiner} that defines classes using {@code MethodHandles.Lookup#defineHiddenClass}. * * @author mcculls@gmail.com (Stuart McCulloch) */ -@SuppressWarnings("SunApi") final class HiddenClassDefiner implements ClassDefiner { - 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; - - /** True if this class err'd during initialization and should not be used. */ - static final boolean HAS_ERROR; + @Override + public Class define(Class hostClass, byte[] bytecode) throws Exception { + Module guiceModule = HiddenClassDefiner.class.getModule(); + Module hostModule = hostClass.getModule(); + if (guiceModule.isNamed() && hostModule.isNamed()) { + if (!guiceModule.canRead(hostModule)) { + guiceModule.addReads(hostModule); + } + if (!hostModule.isOpen(hostClass.getPackageName(), guiceModule)) { + hostModule.addOpens(hostClass.getPackageName(), guiceModule); + } + } - static { - sun.misc.Unsafe theUnsafe; - Object trustedLookupBase; - long trustedLookupOffset; - Object hiddenClassOptions; - Method hiddenDefineMethod; + Lookup initialLookup; try { - theUnsafe = UnsafeGetter.getUnsafe(); - Field trustedLookupField = Lookup.class.getDeclaredField("IMPL_LOOKUP"); - trustedLookupBase = theUnsafe.staticFieldBase(trustedLookupField); - trustedLookupOffset = theUnsafe.staticFieldOffset(trustedLookupField); - hiddenClassOptions = classOptions("NESTMATE"); - hiddenDefineMethod = - Lookup.class.getMethod( - "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; + initialLookup = MethodHandles.privateLookupIn(hostClass, MethodHandles.lookup()); + } catch (IllegalAccessException e) { + initialLookup = MethodHandles.lookup().in(hostClass); } - - THE_UNSAFE = theUnsafe; - TRUSTED_LOOKUP_BASE = trustedLookupBase; - TRUSTED_LOOKUP_OFFSET = trustedLookupOffset; - HIDDEN_CLASS_OPTIONS = hiddenClassOptions; - HIDDEN_DEFINE_METHOD = hiddenDefineMethod; - HAS_ERROR = theUnsafe == null; + return defineClass(initialLookup, bytecode, hostClass); } - @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."); - } + private Class defineClass(Lookup lookup, byte[] bytecode, Class hostClass) throws Exception { + try { + return lookup.defineClass(bytecode); + } catch (IllegalAccessException e) { + // 1) Try hostClass.getModuleLookup() if the host exposes one. + try { + Method getModuleLookup = hostClass.getDeclaredMethod("getModuleLookup"); + getModuleLookup.setAccessible(true); + Lookup nextLookup = (Lookup) getModuleLookup.invoke(null); + if (nextLookup != null && !nextLookup.equals(lookup)) { + return nextLookup.defineClass(bytecode); + } + } catch (Throwable ignored) { + // Ignore and continue with other lookup strategies. + } - Lookup trustedLookup = - (Lookup) THE_UNSAFE.getObject(TRUSTED_LOOKUP_BASE, TRUSTED_LOOKUP_OFFSET); - Lookup definedLookup = - (Lookup) - HIDDEN_DEFINE_METHOD.invoke( - trustedLookup.in(hostClass), bytecode, false, HIDDEN_CLASS_OPTIONS); - return definedLookup.lookupClass(); - } + // 2) Retry with a private lookup. + try { + Lookup nextLookup = MethodHandles.privateLookupIn(hostClass, MethodHandles.lookup()); + if (nextLookup != null && !nextLookup.equals(lookup)) { + return nextLookup.defineClass(bytecode); + } + } catch (IllegalAccessException ignored) { + // Ignore and continue with other lookup strategies. + } + + // 3) Last attempt with lookup().in(hostClass). + Lookup fallbackLookup = MethodHandles.lookup().in(hostClass); + if (!fallbackLookup.equals(lookup)) { + try { + return fallbackLookup.defineClass(bytecode); + } catch (IllegalAccessException ignored) { + // Fall through to rethrow the original access error. + } + } - /** Creates {@link MethodHandles.Lookup.ClassOption} array with the named options. */ - @SuppressWarnings("unchecked") - private static Object classOptions(String... options) throws ClassNotFoundException { - @SuppressWarnings("rawtypes") // Unavoidable, only way to use Enum.valueOf - Class optionClass = Class.forName(Lookup.class.getName() + "$ClassOption"); - Object classOptions = Array.newInstance(optionClass, options.length); - for (int i = 0; i < options.length; i++) { - Array.set(classOptions, i, Enum.valueOf(optionClass, options[i])); + throw e; } - return classOptions; } } diff --git a/core/src/com/google/inject/internal/aop/LookupClassDefiner.java b/core/src/com/google/inject/internal/aop/LookupClassDefiner.java new file mode 100644 index 0000000000..505e37a1ac --- /dev/null +++ b/core/src/com/google/inject/internal/aop/LookupClassDefiner.java @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2020 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; + +import java.security.AccessController; +import java.security.PrivilegedExceptionAction; +import java.util.logging.Level; +import java.util.logging.Logger; + +/** + * {@link ClassDefiner} that defines classes using {@code java.lang.invoke.MethodHandles.Lookup}. + * + * @author mcculls@gmail.com (Stuart McCulloch) + */ +final class LookupClassDefiner implements ClassDefiner { + + private static final Logger logger = Logger.getLogger(LookupClassDefiner.class.getName()); + + private static final ClassDefiner HIDDEN_DEFINER; + + static { + HIDDEN_DEFINER = tryPrivileged(HiddenClassDefiner::new, "Cannot bind HiddenClassDefiner"); + } + + public static boolean isAccessible() { + return HIDDEN_DEFINER != null; + } + + public static boolean canLoadProxyByName(Class hostClass) { + return HIDDEN_DEFINER != null; // lookup-defined classes are normal named classes + } + + @Override + public Class define(Class hostClass, byte[] bytecode) throws Exception { + if (HIDDEN_DEFINER == null) { + throw new IllegalStateException("No class definer available"); + } + return HIDDEN_DEFINER.define(hostClass, bytecode); + } + + static T tryPrivileged(PrivilegedExceptionAction action, String errorMessage) { + try { + return AccessController.doPrivileged(action); + } catch (Throwable e) { + logger.log(Level.FINE, errorMessage, e); + return null; + } + } +} diff --git a/core/src/com/google/inject/internal/aop/UnsafeClassDefiner.java b/core/src/com/google/inject/internal/aop/UnsafeClassDefiner.java deleted file mode 100644 index d3540d28f0..0000000000 --- a/core/src/com/google/inject/internal/aop/UnsafeClassDefiner.java +++ /dev/null @@ -1,220 +0,0 @@ -/* - * Copyright (C) 2020 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; - -import static java.lang.reflect.Modifier.PUBLIC; -import static org.objectweb.asm.ClassWriter.COMPUTE_MAXS; -import static org.objectweb.asm.Opcodes.ACC_SUPER; -import static org.objectweb.asm.Opcodes.ACONST_NULL; -import static org.objectweb.asm.Opcodes.ALOAD; -import static org.objectweb.asm.Opcodes.ARETURN; -import static org.objectweb.asm.Opcodes.ARRAYLENGTH; -import static org.objectweb.asm.Opcodes.CHECKCAST; -import static org.objectweb.asm.Opcodes.ICONST_0; -import static org.objectweb.asm.Opcodes.INVOKESPECIAL; -import static org.objectweb.asm.Opcodes.INVOKEVIRTUAL; -import static org.objectweb.asm.Opcodes.RETURN; -import static org.objectweb.asm.Opcodes.V1_8; - -import com.google.common.cache.CacheBuilder; -import com.google.common.cache.CacheLoader; -import com.google.common.cache.LoadingCache; -import com.google.inject.internal.InternalFlags; -import com.google.inject.internal.InternalFlags.CustomClassLoadingOption; -import java.security.AccessController; -import java.security.PrivilegedExceptionAction; -import java.util.function.BiFunction; -import java.util.logging.Level; -import java.util.logging.Logger; -import org.objectweb.asm.ClassWriter; -import org.objectweb.asm.MethodVisitor; -import org.objectweb.asm.Type; - -/** - * {@link ClassDefiner} that defines classes using {@code sun.misc.Unsafe}. - * - * @author mcculls@gmail.com (Stuart McCulloch) - */ -final class UnsafeClassDefiner implements ClassDefiner { - - private static final Logger logger = Logger.getLogger(UnsafeClassDefiner.class.getName()); - - private static final ClassDefiner UNSAFE_DEFINER; - - static { - ClassDefiner unsafeDefiner = - tryPrivileged(AnonymousClassDefiner::new, "Cannot bind Unsafe.defineAnonymousClass"); - - if (AnonymousClassDefiner.HAS_ERROR || unsafeDefiner == null) { - unsafeDefiner = - tryPrivileged( - HiddenClassDefiner::new, "Cannot bind MethodHandles.Lookup.defineHiddenClass"); - if (HiddenClassDefiner.HAS_ERROR) { - unsafeDefiner = null; - } - } - UNSAFE_DEFINER = unsafeDefiner; - } - - private static final boolean ALWAYS_DEFINE_ANONYMOUSLY = - InternalFlags.getCustomClassLoadingOption() == CustomClassLoadingOption.ANONYMOUS; - - private static final String DEFINEACCESS_BY_GUICE_MARKER = "$$DefineAccessByGuice$$"; - - private static final String[] DEFINEACCESS_API = {"java/util/function/BiFunction"}; - - private static final String CLASS_LOADER_TYPE = Type.getInternalName(ClassLoader.class); - - private static final String BYTE_ARRAY_TYPE = Type.getInternalName(byte[].class); - - // initialization-on-demand... - private static class ClassLoaderDefineClassHolder { - static final ClassDefiner CLASS_LOADER_DEFINE_CLASS = - tryPrivileged( - () -> accessDefineClass(ClassLoader.class), "Cannot access ClassLoader.defineClass"); - } - - // initialization-on-demand... - private static class DefineClassCacheHolder { - static final LoadingCache, ClassDefiner> DEFINE_CLASS_CACHE = - CacheBuilder.newBuilder() - .weakKeys() - .build(CacheLoader.from(UnsafeClassDefiner::tryAccessDefineClass)); - } - - /** Do we have access to {@code sun.misc.Unsafe}? */ - public static boolean isAccessible() { - return UNSAFE_DEFINER != null; - } - - /** Returns true if it's possible to load by name proxies defined from the given host. */ - public static boolean canLoadProxyByName(Class hostClass) { - return findClassDefiner(hostClass.getClassLoader()) != UNSAFE_DEFINER; - } - - /** Returns true if it's possible to downcast to proxies defined from the given host. */ - public static boolean canDowncastToProxy(Class hostClass) { - return !(findClassDefiner(hostClass.getClassLoader()) instanceof AnonymousClassDefiner); - } - - @Override - public Class define(Class hostClass, byte[] bytecode) throws Exception { - return findClassDefiner(hostClass.getClassLoader()).define(hostClass, bytecode); - } - - /** Finds the appropriate class definer for the given class loader. */ - private static ClassDefiner findClassDefiner(ClassLoader hostLoader) { - if (hostLoader == null || ALWAYS_DEFINE_ANONYMOUSLY) { - return UNSAFE_DEFINER; - } else if (ClassLoaderDefineClassHolder.CLASS_LOADER_DEFINE_CLASS != null) { - // we have access to the defineClass method of anything extending ClassLoader - return ClassLoaderDefineClassHolder.CLASS_LOADER_DEFINE_CLASS; - } else { - // can't access ClassLoader, try accessing the specific sub-class instead - return DefineClassCacheHolder.DEFINE_CLASS_CACHE.getUnchecked(hostLoader.getClass()); - } - } - - static T tryPrivileged(PrivilegedExceptionAction action, String errorMessage) { - try { - return AccessController.doPrivileged(action); - } catch (Throwable e) { - logger.log(Level.FINE, errorMessage, e); - return null; - } - } - - static ClassDefiner tryAccessDefineClass(Class loaderClass) { - try { - logger.log(Level.FINE, "Accessing defineClass method in %s", loaderClass); - return AccessController.doPrivileged( - (PrivilegedExceptionAction) () -> accessDefineClass(loaderClass)); - } catch (Throwable e) { - logger.log(Level.FINE, "Cannot access defineClass method in " + loaderClass, e); - return UNSAFE_DEFINER; - } - } - - /** Generates helper in same package as the {@link ClassLoader} so it can access defineClass */ - @SuppressWarnings("unchecked") - static ClassDefiner accessDefineClass(Class loaderClass) throws Exception { - byte[] bytecode = buildDefineClassAccess(loaderClass); - Class accessClass = UNSAFE_DEFINER.define(loaderClass, bytecode); - return new GeneratedClassDefiner( - (BiFunction>) - accessClass.getDeclaredConstructor().newInstance()); - } - - /** {@link ClassLoader} helper that sits in the same package and passes on defineClass requests */ - private static byte[] buildDefineClassAccess(Class loaderClass) { - ClassWriter cw = new ClassWriter(COMPUTE_MAXS); - - // target Java8 because that's all we need for the generated helper - cw.visit( - V1_8, - PUBLIC | ACC_SUPER, - loaderClass.getName().replace('.', '/') + DEFINEACCESS_BY_GUICE_MARKER, - null, - "java/lang/Object", - DEFINEACCESS_API); - - MethodVisitor mv; - - mv = cw.visitMethod(PUBLIC, "", "()V", null, null); - mv.visitCode(); - mv.visitVarInsn(ALOAD, 0); - mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "", "()V", false); - mv.visitInsn(RETURN); - mv.visitMaxs(0, 0); - mv.visitEnd(); - - mv = - cw.visitMethod( - PUBLIC, - "apply", - "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;", - null, - null); - - mv.visitCode(); - - mv.visitVarInsn(ALOAD, 1); - mv.visitTypeInsn(CHECKCAST, CLASS_LOADER_TYPE); - mv.visitInsn(ACONST_NULL); - mv.visitVarInsn(ALOAD, 2); - mv.visitTypeInsn(CHECKCAST, BYTE_ARRAY_TYPE); - mv.visitInsn(ICONST_0); - mv.visitVarInsn(ALOAD, 2); - mv.visitTypeInsn(CHECKCAST, BYTE_ARRAY_TYPE); - mv.visitInsn(ARRAYLENGTH); - - mv.visitMethodInsn( - INVOKEVIRTUAL, - "java/lang/ClassLoader", - "defineClass", - "(Ljava/lang/String;[BII)Ljava/lang/Class;", - false); - - mv.visitInsn(ARETURN); - - mv.visitMaxs(0, 0); - mv.visitEnd(); - cw.visitEnd(); - - return cw.toByteArray(); - } -} diff --git a/core/src/com/google/inject/internal/aop/UnsafeGetter.java b/core/src/com/google/inject/internal/aop/UnsafeGetter.java deleted file mode 100644 index f0f5e9be20..0000000000 --- a/core/src/com/google/inject/internal/aop/UnsafeGetter.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * 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; - -@SuppressWarnings("SunApi") -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"); - } -} diff --git a/pom.xml b/pom.xml index 9c2e31e8ee..2760cc57ad 100644 --- a/pom.xml +++ b/pom.xml @@ -276,7 +276,7 @@ See the Apache License Version 2.0 for the specific language governing permissio maven-compiler-plugin 3.11.0 - 11 + 15 -parameters