aboutsummaryrefslogtreecommitdiff
path: root/src/Java/shaded/reflectionfactory/ReflectionFactory.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/Java/shaded/reflectionfactory/ReflectionFactory.java')
-rw-r--r--src/Java/shaded/reflectionfactory/ReflectionFactory.java706
1 files changed, 706 insertions, 0 deletions
diff --git a/src/Java/shaded/reflectionfactory/ReflectionFactory.java b/src/Java/shaded/reflectionfactory/ReflectionFactory.java
new file mode 100644
index 0000000000..6692e827dd
--- /dev/null
+++ b/src/Java/shaded/reflectionfactory/ReflectionFactory.java
@@ -0,0 +1,706 @@
+/*
+ * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package shaded.reflectionfactory;
+
+import java.io.Externalizable;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.ObjectStreamClass;
+import java.io.OptionalDataException;
+import java.io.Serializable;
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.reflect.Field;
+import java.lang.reflect.Executable;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Modifier;
+import java.security.AccessController;
+import java.security.Permission;
+import java.security.PrivilegedAction;
+import java.util.Objects;
+
+
+/** <P> The master factory for all reflective objects, both those in
+ java.lang.reflect (Fields, Methods, Constructors) as well as their
+ delegates (FieldAccessors, MethodAccessors, ConstructorAccessors).
+ </P>
+
+ <P> The methods in this class are extremely unsafe and can cause
+ subversion of both the language and the verifier. For this reason,
+ they are all instance methods, and access to the constructor of
+ this factory is guarded by a security check, in similar style to
+ sun.misc.Unsafe. </P>
+*/
+
+public class ReflectionFactory {
+
+ private static boolean initted = false;
+ private static final Permission reflectionFactoryAccessPerm
+ = new RuntimePermission("reflectionFactoryAccess");
+ private static final ReflectionFactory soleInstance = new ReflectionFactory();
+ // Provides access to package-private mechanisms in java.lang.reflect
+ private static volatile LangReflectAccess langReflectAccess;
+
+ /* Method for static class initializer <clinit>, or null */
+ private static volatile Method hasStaticInitializerMethod;
+
+ //
+ // "Inflation" mechanism. Loading bytecodes to implement
+ // Method.invoke() and Constructor.newInstance() currently costs
+ // 3-4x more than an invocation via native code for the first
+ // invocation (though subsequent invocations have been benchmarked
+ // to be over 20x faster). Unfortunately this cost increases
+ // startup time for certain applications that use reflection
+ // intensively (but only once per class) to bootstrap themselves.
+ // To avoid this penalty we reuse the existing JVM entry points
+ // for the first few invocations of Methods and Constructors and
+ // then switch to the bytecode-based implementations.
+ //
+ // Package-private to be accessible to NativeMethodAccessorImpl
+ // and NativeConstructorAccessorImpl
+ private static boolean noInflation = false;
+ private static int inflationThreshold = 15;
+
+ private ReflectionFactory() {}
+
+ /**
+ * A convenience class for acquiring the capability to instantiate
+ * reflective objects. Use this instead of a raw call to {@link
+ * #getReflectionFactory} in order to avoid being limited by the
+ * permissions of your callers.
+ *
+ * <p>An instance of this class can be used as the argument of
+ * <code>AccessController.doPrivileged</code>.
+ */
+ public static final class GetReflectionFactoryAction
+ implements PrivilegedAction<ReflectionFactory> {
+ public ReflectionFactory run() {
+ return getReflectionFactory();
+ }
+ }
+
+ /**
+ * Provides the caller with the capability to instantiate reflective
+ * objects.
+ *
+ * <p> First, if there is a security manager, its
+ * <code>checkPermission</code> method is called with a {@link
+ * java.lang.RuntimePermission} with target
+ * <code>"reflectionFactoryAccess"</code>. This may result in a
+ * security exception.
+ *
+ * <p> The returned <code>ReflectionFactory</code> object should be
+ * carefully guarded by the caller, since it can be used to read and
+ * write private data and invoke private methods, as well as to load
+ * unverified bytecodes. It must never be passed to untrusted code.
+ *
+ * @exception SecurityException if a security manager exists and its
+ * <code>checkPermission</code> method doesn't allow
+ * access to the RuntimePermission "reflectionFactoryAccess". */
+ public static ReflectionFactory getReflectionFactory() {
+ SecurityManager security = System.getSecurityManager();
+ if (security != null) {
+ // TO DO: security.checkReflectionFactoryAccess();
+ security.checkPermission(reflectionFactoryAccessPerm);
+ }
+ return soleInstance;
+ }
+
+ //--------------------------------------------------------------------------
+ //
+ // Routines used by java.lang.reflect
+ //
+ //
+
+ /** Called only by java.lang.reflect.Modifier's static initializer */
+ public void setLangReflectAccess(LangReflectAccess access) {
+ langReflectAccess = access;
+ }
+
+ /**
+ * Note: this routine can cause the declaring class for the field
+ * be initialized and therefore must not be called until the
+ * first get/set of this field.
+ * @param field the field
+ * @param override true if caller has overridden aaccessibility
+ */
+ public FieldAccessor newFieldAccessor(Field field, boolean override) {
+ checkInitted();
+ return UnsafeFieldAccessorFactory.newFieldAccessor(field, override);
+ }
+
+ public MethodAccessor newMethodAccessor(Method method) {
+ checkInitted();
+
+ if (noInflation && !ReflectUtil.isVMAnonymousClass(method.getDeclaringClass())) {
+ return new MethodAccessorGenerator().
+ generateMethod(method.getDeclaringClass(),
+ method.getName(),
+ method.getParameterTypes(),
+ method.getReturnType(),
+ method.getExceptionTypes(),
+ method.getModifiers());
+ } else {
+ NativeMethodAccessorImpl acc =
+ new NativeMethodAccessorImpl(method);
+ DelegatingMethodAccessorImpl res =
+ new DelegatingMethodAccessorImpl(acc);
+ acc.setParent(res);
+ return res;
+ }
+ }
+
+ public ConstructorAccessor newConstructorAccessor(Constructor<?> c) {
+ checkInitted();
+
+ Class<?> declaringClass = c.getDeclaringClass();
+ if (Modifier.isAbstract(declaringClass.getModifiers())) {
+ return new InstantiationExceptionConstructorAccessorImpl(null);
+ }
+ if (declaringClass == Class.class) {
+ return new InstantiationExceptionConstructorAccessorImpl
+ ("Can not instantiate java.lang.Class");
+ }
+ // Bootstrapping issue: since we use Class.newInstance() in
+ // the ConstructorAccessor generation process, we have to
+ // break the cycle here.
+ if (Reflection.isSubclassOf(declaringClass,
+ ConstructorAccessorImpl.class)) {
+ return new BootstrapConstructorAccessorImpl(c);
+ }
+
+ if (noInflation && !ReflectUtil.isVMAnonymousClass(c.getDeclaringClass())) {
+ return new MethodAccessorGenerator().
+ generateConstructor(c.getDeclaringClass(),
+ c.getParameterTypes(),
+ c.getExceptionTypes(),
+ c.getModifiers());
+ } else {
+ NativeConstructorAccessorImpl acc =
+ new NativeConstructorAccessorImpl(c);
+ DelegatingConstructorAccessorImpl res =
+ new DelegatingConstructorAccessorImpl(acc);
+ acc.setParent(res);
+ return res;
+ }
+ }
+
+ //--------------------------------------------------------------------------
+ //
+ // Routines used by java.lang
+ //
+ //
+
+ /** Creates a new java.lang.reflect.Field. Access checks as per
+ java.lang.reflect.AccessibleObject are not overridden. */
+ public Field newField(Class<?> declaringClass,
+ String name,
+ Class<?> type,
+ int modifiers,
+ int slot,
+ String signature,
+ byte[] annotations)
+ {
+ return langReflectAccess().newField(declaringClass,
+ name,
+ type,
+ modifiers,
+ slot,
+ signature,
+ annotations);
+ }
+
+ /** Creates a new java.lang.reflect.Method. Access checks as per
+ java.lang.reflect.AccessibleObject are not overridden. */
+ public Method newMethod(Class<?> declaringClass,
+ String name,
+ Class<?>[] parameterTypes,
+ Class<?> returnType,
+ Class<?>[] checkedExceptions,
+ int modifiers,
+ int slot,
+ String signature,
+ byte[] annotations,
+ byte[] parameterAnnotations,
+ byte[] annotationDefault)
+ {
+ return langReflectAccess().newMethod(declaringClass,
+ name,
+ parameterTypes,
+ returnType,
+ checkedExceptions,
+ modifiers,
+ slot,
+ signature,
+ annotations,
+ parameterAnnotations,
+ annotationDefault);
+ }
+
+ /** Creates a new java.lang.reflect.Constructor. Access checks as
+ per java.lang.reflect.AccessibleObject are not overridden. */
+ public Constructor<?> newConstructor(Class<?> declaringClass,
+ Class<?>[] parameterTypes,
+ Class<?>[] checkedExceptions,
+ int modifiers,
+ int slot,
+ String signature,
+ byte[] annotations,
+ byte[] parameterAnnotations)
+ {
+ return langReflectAccess().newConstructor(declaringClass,
+ parameterTypes,
+ checkedExceptions,
+ modifiers,
+ slot,
+ signature,
+ annotations,
+ parameterAnnotations);
+ }
+
+ /** Gets the MethodAccessor object for a java.lang.reflect.Method */
+ public MethodAccessor getMethodAccessor(Method m) {
+ return langReflectAccess().getMethodAccessor(m);
+ }
+
+ /** Sets the MethodAccessor object for a java.lang.reflect.Method */
+ public void setMethodAccessor(Method m, MethodAccessor accessor) {
+ langReflectAccess().setMethodAccessor(m, accessor);
+ }
+
+ /** Gets the ConstructorAccessor object for a
+ java.lang.reflect.Constructor */
+ public ConstructorAccessor getConstructorAccessor(Constructor<?> c) {
+ return langReflectAccess().getConstructorAccessor(c);
+ }
+
+ /** Sets the ConstructorAccessor object for a
+ java.lang.reflect.Constructor */
+ public void setConstructorAccessor(Constructor<?> c,
+ ConstructorAccessor accessor)
+ {
+ langReflectAccess().setConstructorAccessor(c, accessor);
+ }
+
+ /** Makes a copy of the passed method. The returned method is a
+ "child" of the passed one; see the comments in Method.java for
+ details. */
+ public Method copyMethod(Method arg) {
+ return langReflectAccess().copyMethod(arg);
+ }
+
+ /** Makes a copy of the passed field. The returned field is a
+ "child" of the passed one; see the comments in Field.java for
+ details. */
+ public Field copyField(Field arg) {
+ return langReflectAccess().copyField(arg);
+ }
+
+ /** Makes a copy of the passed constructor. The returned
+ constructor is a "child" of the passed one; see the comments
+ in Constructor.java for details. */
+ public <T> Constructor<T> copyConstructor(Constructor<T> arg) {
+ return langReflectAccess().copyConstructor(arg);
+ }
+
+ /** Gets the byte[] that encodes TypeAnnotations on an executable.
+ */
+ public byte[] getExecutableTypeAnnotationBytes(Executable ex) {
+ return langReflectAccess().getExecutableTypeAnnotationBytes(ex);
+ }
+
+ //--------------------------------------------------------------------------
+ //
+ // Routines used by serialization
+ //
+ //
+
+ /**
+ * Returns an accessible constructor capable of creating instances
+ * of the given class, initialized by the given constructor.
+ *
+ * @param classToInstantiate the class to instantiate
+ * @param constructorToCall the constructor to call
+ * @return an accessible constructor
+ */
+ public Constructor<?> newConstructorForSerialization
+ (Class<?> classToInstantiate, Constructor<?> constructorToCall)
+ {
+ // Fast path
+ if (constructorToCall.getDeclaringClass() == classToInstantiate) {
+ return constructorToCall;
+ }
+ return generateConstructor(classToInstantiate, constructorToCall);
+ }
+
+ /**
+ * Returns an accessible no-arg constructor for a class.
+ * The no-arg constructor is found searching the class and its supertypes.
+ *
+ * @param cl the class to instantiate
+ * @return a no-arg constructor for the class or {@code null} if
+ * the class or supertypes do not have a suitable no-arg constructor
+ */
+ public final Constructor<?> newConstructorForSerialization(Class<?> cl) {
+ Class<?> initCl = cl;
+ while (Serializable.class.isAssignableFrom(initCl)) {
+ if ((initCl = initCl.getSuperclass()) == null) {
+ return null;
+ }
+ }
+ Constructor<?> constructorToCall;
+ try {
+ constructorToCall = initCl.getDeclaredConstructor();
+ int mods = constructorToCall.getModifiers();
+ if ((mods & Modifier.PRIVATE) != 0 ||
+ ((mods & (Modifier.PUBLIC | Modifier.PROTECTED)) == 0 &&
+ !packageEquals(cl, initCl))) {
+ return null;
+ }
+ } catch (NoSuchMethodException ex) {
+ return null;
+ }
+ return generateConstructor(cl, constructorToCall);
+ }
+
+ private final Constructor<?> generateConstructor(Class<?> classToInstantiate,
+ Constructor<?> constructorToCall) {
+
+
+ ConstructorAccessor acc = new MethodAccessorGenerator().
+ generateSerializationConstructor(classToInstantiate,
+ constructorToCall.getParameterTypes(),
+ constructorToCall.getExceptionTypes(),
+ constructorToCall.getModifiers(),
+ constructorToCall.getDeclaringClass());
+ Constructor<?> c = newConstructor(constructorToCall.getDeclaringClass(),
+ constructorToCall.getParameterTypes(),
+ constructorToCall.getExceptionTypes(),
+ constructorToCall.getModifiers(),
+ langReflectAccess().
+ getConstructorSlot(constructorToCall),
+ langReflectAccess().
+ getConstructorSignature(constructorToCall),
+ langReflectAccess().
+ getConstructorAnnotations(constructorToCall),
+ langReflectAccess().
+ getConstructorParameterAnnotations(constructorToCall));
+ setConstructorAccessor(c, acc);
+ c.setAccessible(true);
+ return c;
+ }
+
+ /**
+ * Returns an accessible no-arg constructor for an externalizable class to be
+ * initialized using a public no-argument constructor.
+ *
+ * @param cl the class to instantiate
+ * @return A no-arg constructor for the class; returns {@code null} if
+ * the class does not implement {@link java.io.Externalizable}
+ */
+ public final Constructor<?> newConstructorForExternalization(Class<?> cl) {
+ if (!Externalizable.class.isAssignableFrom(cl)) {
+ return null;
+ }
+ try {
+ Constructor<?> cons = cl.getConstructor();
+ cons.setAccessible(true);
+ return cons;
+ } catch (NoSuchMethodException ex) {
+ return null;
+ }
+ }
+
+ /**
+ * Returns a direct MethodHandle for the {@code readObject} method on
+ * a Serializable class.
+ * The first argument of {@link MethodHandle#invoke} is the serializable
+ * object and the second argument is the {@code ObjectInputStream} passed to
+ * {@code readObject}.
+ *
+ * @param cl a Serializable class
+ * @return a direct MethodHandle for the {@code readObject} method of the class or
+ * {@code null} if the class does not have a {@code readObject} method
+ */
+ public final MethodHandle readObjectForSerialization(Class<?> cl) {
+ return findReadWriteObjectForSerialization(cl, "readObject", ObjectInputStream.class);
+ }
+
+ /**
+ * Returns a direct MethodHandle for the {@code readObjectNoData} method on
+ * a Serializable class.
+ * The first argument of {@link MethodHandle#invoke} is the serializable
+ * object and the second argument is the {@code ObjectInputStream} passed to
+ * {@code readObjectNoData}.
+ *
+ * @param cl a Serializable class
+ * @return a direct MethodHandle for the {@code readObjectNoData} method
+ * of the class or {@code null} if the class does not have a
+ * {@code readObjectNoData} method
+ */
+ public final MethodHandle readObjectNoDataForSerialization(Class<?> cl) {
+ return findReadWriteObjectForSerialization(cl, "readObjectNoData", ObjectInputStream.class);
+ }
+
+ /**
+ * Returns a direct MethodHandle for the {@code writeObject} method on
+ * a Serializable class.
+ * The first argument of {@link MethodHandle#invoke} is the serializable
+ * object and the second argument is the {@code ObjectOutputStream} passed to
+ * {@code writeObject}.
+ *
+ * @param cl a Serializable class
+ * @return a direct MethodHandle for the {@code writeObject} method of the class or
+ * {@code null} if the class does not have a {@code writeObject} method
+ */
+ public final MethodHandle writeObjectForSerialization(Class<?> cl) {
+ return findReadWriteObjectForSerialization(cl, "writeObject", ObjectOutputStream.class);
+ }
+
+ private final MethodHandle findReadWriteObjectForSerialization(Class<?> cl,
+ String methodName,
+ Class<?> streamClass) {
+ if (!Serializable.class.isAssignableFrom(cl)) {
+ return null;
+ }
+
+ try {
+ Method meth = cl.getDeclaredMethod(methodName, streamClass);
+ int mods = meth.getModifiers();
+ if (meth.getReturnType() != Void.TYPE ||
+ Modifier.isStatic(mods) ||
+ !Modifier.isPrivate(mods)) {
+ return null;
+ }
+ meth.setAccessible(true);
+ return MethodHandles.lookup().unreflect(meth);
+ } catch (NoSuchMethodException ex) {
+ return null;
+ } catch (IllegalAccessException ex1) {
+ throw new InternalError("Error", ex1);
+ }
+ }
+
+ /**
+ * Returns a direct MethodHandle for the {@code readResolve} method on
+ * a serializable class.
+ * The single argument of {@link MethodHandle#invoke} is the serializable
+ * object.
+ *
+ * @param cl the Serializable class
+ * @return a direct MethodHandle for the {@code readResolve} method of the class or
+ * {@code null} if the class does not have a {@code readResolve} method
+ */
+ public final MethodHandle readResolveForSerialization(Class<?> cl) {
+ return getReplaceResolveForSerialization(cl, "readResolve");
+ }
+
+ /**
+ * Returns a direct MethodHandle for the {@code writeReplace} method on
+ * a serializable class.
+ * The single argument of {@link MethodHandle#invoke} is the serializable
+ * object.
+ *
+ * @param cl the Serializable class
+ * @return a direct MethodHandle for the {@code writeReplace} method of the class or
+ * {@code null} if the class does not have a {@code writeReplace} method
+ */
+ public final MethodHandle writeReplaceForSerialization(Class<?> cl) {
+ return getReplaceResolveForSerialization(cl, "writeReplace");
+ }
+
+ /**
+ * Returns a direct MethodHandle for the {@code writeReplace} method on
+ * a serializable class.
+ * The single argument of {@link MethodHandle#invoke} is the serializable
+ * object.
+ *
+ * @param cl the Serializable class
+ * @return a direct MethodHandle for the {@code writeReplace} method of the class or
+ * {@code null} if the class does not have a {@code writeReplace} method
+ */
+ private MethodHandle getReplaceResolveForSerialization(Class<?> cl,
+ String methodName) {
+ if (!Serializable.class.isAssignableFrom(cl)) {
+ return null;
+ }
+
+ Class<?> defCl = cl;
+ while (defCl != null) {
+ try {
+ Method m = defCl.getDeclaredMethod(methodName);
+ if (m.getReturnType() != Object.class) {
+ return null;
+ }
+ int mods = m.getModifiers();
+ if (Modifier.isStatic(mods) | Modifier.isAbstract(mods)) {
+ return null;
+ } else if (Modifier.isPublic(mods) | Modifier.isProtected(mods)) {
+ // fall through
+ } else if (Modifier.isPrivate(mods) && (cl != defCl)) {
+ return null;
+ } else if (!packageEquals(cl, defCl)) {
+ return null;
+ }
+ try {
+ // Normal return
+ m.setAccessible(true);
+ return MethodHandles.lookup().unreflect(m);
+ } catch (IllegalAccessException ex0) {
+ // setAccessible should prevent IAE
+ throw new InternalError("Error", ex0);
+ }
+ } catch (NoSuchMethodException ex) {
+ defCl = defCl.getSuperclass();
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Returns true if the class has a static initializer.
+ * The presence of a static initializer is used to compute the serialVersionUID.
+ * @param cl a serializable classLook
+ * @return {@code true} if the class has a static initializer,
+ * otherwise {@code false}
+ */
+ public final boolean hasStaticInitializerForSerialization(Class<?> cl) {
+ Method m = hasStaticInitializerMethod;
+ if (m == null) {
+ try {
+ m = ObjectStreamClass.class.getDeclaredMethod("hasStaticInitializer",
+ new Class<?>[]{Class.class});
+ m.setAccessible(true);
+ hasStaticInitializerMethod = m;
+ } catch (NoSuchMethodException ex) {
+ throw new InternalError("No such method hasStaticInitializer on "
+ + ObjectStreamClass.class, ex);
+ }
+ }
+ try {
+ return (Boolean) m.invoke(null, cl);
+ } catch (InvocationTargetException | IllegalAccessException ex) {
+ throw new InternalError("Exception invoking hasStaticInitializer", ex);
+ }
+ }
+
+ /**
+ * Returns a new OptionalDataException with {@code eof} set to {@code true}
+ * or {@code false}.
+ * @param bool the value of {@code eof} in the created OptionalDataException
+ * @return a new OptionalDataException
+ */
+ public final OptionalDataException newOptionalDataExceptionForSerialization(boolean bool) {
+ try {
+ Constructor<OptionalDataException> boolCtor =
+ OptionalDataException.class.getDeclaredConstructor(Boolean.TYPE);
+ boolCtor.setAccessible(true);
+ return boolCtor.newInstance(bool);
+ } catch (NoSuchMethodException | InstantiationException|
+ IllegalAccessException|InvocationTargetException ex) {
+ throw new InternalError("unable to create OptionalDataException", ex);
+ }
+ }
+
+ //--------------------------------------------------------------------------
+ //
+ // Internals only below this point
+ //
+
+ static int inflationThreshold() {
+ return inflationThreshold;
+ }
+
+ /** We have to defer full initialization of this class until after
+ the static initializer is run since java.lang.reflect.Method's
+ static initializer (more properly, that for
+ java.lang.reflect.AccessibleObject) causes this class's to be
+ run, before the system properties are set up. */
+ private static void checkInitted() {
+ if (initted) return;
+ AccessController.doPrivileged(
+ new PrivilegedAction<Void>() {
+ public Void run() {
+ // Tests to ensure the system properties table is fully
+ // initialized. This is needed because reflection code is
+ // called very early in the initialization process (before
+ // command-line arguments have been parsed and therefore
+ // these user-settable properties installed.) We assume that
+ // if System.out is non-null then the System class has been
+ // fully initialized and that the bulk of the startup code
+ // has been run.
+
+ if (System.out == null) {
+ // java.lang.System not yet fully initialized
+ return null;
+ }
+
+ String val = System.getProperty("sun.reflect.noInflation");
+ if (val != null && val.equals("true")) {
+ noInflation = true;
+ }
+
+ val = System.getProperty("sun.reflect.inflationThreshold");
+ if (val != null) {
+ try {
+ inflationThreshold = Integer.parseInt(val);
+ } catch (NumberFormatException e) {
+ throw new RuntimeException("Unable to parse property sun.reflect.inflationThreshold", e);
+ }
+ }
+
+ initted = true;
+ return null;
+ }
+ });
+ }
+
+ private static LangReflectAccess langReflectAccess() {
+ if (langReflectAccess == null) {
+ // Call a static method to get class java.lang.reflect.Modifier
+ // initialized. Its static initializer will cause
+ // setLangReflectAccess() to be called from the context of the
+ // java.lang.reflect package.
+ Modifier.isPublic(Modifier.PUBLIC);
+ }
+ return langReflectAccess;
+ }
+
+ /**
+ * Returns true if classes are defined in the classloader and same package, false
+ * otherwise.
+ * @param cl1 a class
+ * @param cl2 another class
+ * @returns true if the two classes are in the same classloader and package
+ */
+ private static boolean packageEquals(Class<?> cl1, Class<?> cl2) {
+ return cl1.getClassLoader() == cl2.getClassLoader() &&
+ Objects.equals(cl1.getPackage(), cl2.getPackage());
+ }
+
+}