All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.glassfish.pfl.basic.reflection.BridgeBase Maven / Gradle / Ivy

There is a newer version: 5.0.0
Show newest version
/*
 * Copyright (c) 2018, 2019 Oracle and/or its affiliates. All rights reserved.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Distribution License v. 1.0, which is available at
 * http://www.eclipse.org/org/documents/edl-v10.php.
 *
 * SPDX-License-Identifier: BSD-3-Clause
 */

package org.glassfish.pfl.basic.reflection;

import sun.misc.Unsafe;

import java.io.OptionalDataException;
import java.lang.invoke.MethodHandle;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.security.ProtectionDomain;

public abstract class BridgeBase {
    /**
     * This constant differs from all results that will ever be returned from
     * {@link #objectFieldOffset}.
     */
    public static final long INVALID_FIELD_OFFSET = -1;

    private final Unsafe unsafe = AccessController.doPrivileged(
                    new PrivilegedAction() {
                        public Unsafe run() {
                            try {
                                Field field = Unsafe.class.getDeclaredField("theUnsafe");
                                field.setAccessible(true);
                                return (Unsafe) field.get(null);
                            } catch (NoSuchFieldException | IllegalAccessException exc) {
                                throw new Error("Could not access Unsafe", exc);
                            }
                        }
                    }
            );

    /**
     * Fetches a field element within the given
     * object o at the given offset.
     * The result is undefined unless the offset was obtained from
     * {@link #objectFieldOffset} on the {@link java.lang.reflect.Field}
     * of some Java field and the object referred to by o
     * is of a class compatible with that field's class.
     *
     * @param o      Java heap object in which the field from which the offset
     *               was obtained resides
     * @param offset indication of where the field resides in a Java heap
     *               object
     * @return the value fetched from the indicated Java field
     * @throws RuntimeException No defined exceptions are thrown, not even
     *                          {@link NullPointerException}
     */
    public final int getInt(Object o, long offset) {
        return unsafe.getInt(o, offset);
    }

    /**
     * Stores a value into a given Java field.
     * 

* The first two parameters are interpreted exactly as with * {@link #getInt(Object, long)} to refer to a specific * Java field. The given value is stored into that field. *

* The field must be of the same type as the method * parameter x. * * @param o Java heap object in which the field resides, if any, else * null * @param offset indication of where the field resides in a Java heap * object. * @param x the value to store into the indicated Java field * @throws RuntimeException No defined exceptions are thrown, not even * {@link NullPointerException} */ public final void putInt(Object o, long offset, int x) { if (offset != INVALID_FIELD_OFFSET) unsafe.putInt(o, offset, x); } /** * @see #getInt(Object, long) */ @SuppressWarnings("unchecked") public final T getObject(Object o, long offset) { return (T) unsafe.getObject(o, offset); } /** * @see #putInt(Object, long, int) */ public final void putObject(Object o, long offset, Object x) { if (offset != INVALID_FIELD_OFFSET) unsafe.putObject(o, offset, x); } /** * @see #getInt(Object, long) */ public final boolean getBoolean(Object o, long offset) { return unsafe.getBoolean(o, offset); } /** * @see #putInt(Object, long, int) */ public final void putBoolean(Object o, long offset, boolean x) { if (offset != INVALID_FIELD_OFFSET) unsafe.putBoolean(o, offset, x); } /** * @see #getInt(Object, long) */ public final byte getByte(Object o, long offset) { return unsafe.getByte(o, offset); } /** * @see #putInt(Object, long, int) */ public final void putByte(Object o, long offset, byte x) { if (offset != INVALID_FIELD_OFFSET) unsafe.putByte(o, offset, x); } /** * @see #getInt(Object, long) */ public final short getShort(Object o, long offset) { return unsafe.getShort(o, offset); } /** * @see #putInt(Object, long, int) */ public final void putShort(Object o, long offset, short x) { if (offset != INVALID_FIELD_OFFSET) unsafe.putShort(o, offset, x); } /** * @see #getInt(Object, long) */ public final char getChar(Object o, long offset) { return unsafe.getChar(o, offset); } /** * @see #putInt(Object, long, int) */ public final void putChar(Object o, long offset, char x) { if (offset != INVALID_FIELD_OFFSET) unsafe.putChar(o, offset, x); } /** * @see #getInt(Object, long) */ public final long getLong(Object o, long offset) { return unsafe.getLong(o, offset); } /** * @see #putInt(Object, long, int) */ public final void putLong(Object o, long offset, long x) { if (offset != INVALID_FIELD_OFFSET) unsafe.putLong(o, offset, x); } /** * @see #getInt(Object, long) */ public final float getFloat(Object o, long offset) { return unsafe.getFloat(o, offset); } /** * @see #putInt(Object, long, int) */ public final void putFloat(Object o, long offset, float x) { if (offset != INVALID_FIELD_OFFSET) unsafe.putFloat(o, offset, x); } /** * @see #getInt(Object, long) */ public final double getDouble(Object o, long offset) { return unsafe.getDouble(o, offset); } /** * @see #putInt(Object, long, int) */ public final void putDouble(Object o, long offset, double x) { if (offset != INVALID_FIELD_OFFSET) unsafe.putDouble(o, offset, x); } /** * Returns the offset of a non-static field, which can be passed into the set... or get... methods. * @see #getInt(Object, long) */ public final long objectFieldOffset(Field f) { return unsafe.objectFieldOffset(f); } public final long staticFieldOffset(Field f) { return unsafe.staticFieldOffset(f); } /** * Throw the exception. * The exception may be an undeclared checked exception. */ public final void throwException(Throwable ee) { unsafe.throwException(ee); } /** * Defines a class is a specified classloader. * @param className the name of the class * @param classBytes the byte code for the class * @param classLoader the classloader in which it is to be defined * @param protectionDomain the domain in which the class should be defined * * @deprecated will not work in Java 11 or later. Use {@link #defineClass(Class, String, byte[])} instead */ @SuppressWarnings("DeprecatedIsStillUsed") @Deprecated public Class defineClass(String className, byte[] classBytes, ClassLoader classLoader, ProtectionDomain protectionDomain) { return unsafe.defineClass(className, classBytes, 0, classBytes.length, classLoader, null); } /** * Defines a new class from bytecode. The class will be defined in the classloader and package associated with a * specified 'anchor class'. * * @param anchorClass the class from which the package and classloader of the new class are to be taken. * @param className the name of the class to define * @param classBytes the bytes used to define the class * @return a new instantiable class, in the package and classloader of the anchor class. */ @SuppressWarnings("deprecation") public Class defineClass(Class anchorClass, String className, byte[] classBytes) { return defineClass(className, classBytes, anchorClass.getClassLoader(), null); } /** * Ensure that the class has been initialized. * @param cl the class to ensure is initialized */ public final void ensureClassInitialized(Class cl) { unsafe.ensureClassInitialized(cl); } /** * Obtain the latest user defined ClassLoader from the call stack. * This is required by the RMI-IIOP specification. */ public abstract ClassLoader getLatestUserDefinedLoader(); /** * Return a constructor that can be used to create an instance of the class for externalization. * @param cl the class */ public abstract Constructor newConstructorForExternalization(Class cl); /** * Return a no-arg constructor for the specified class which invokes the specified constructor. * * @param aClass the class for which a constructor should be returned. * @param cons the default constructor on which to model the new constructor. */ public abstract Constructor newConstructorForSerialization(Class aClass, Constructor cons); /** * Return a no-arg constructor for the specified class, based on the default constructor * for its nearest non-serializable base class. * @param aClass the class for which a constructor should be returned. */ public abstract Constructor newConstructorForSerialization(Class aClass); /** * Returns true if the given class defines a static initializer method, * false otherwise. */ public abstract boolean hasStaticInitializerForSerialization(Class cl); /** * Returns a method handle to allow invocation of the specified class's writeObject method. * @param cl the class containing the method */ public abstract MethodHandle writeObjectForSerialization(Class cl) throws NoSuchMethodException, IllegalAccessException; /** * Returns a method handle to allow invocation of the specified class's readObject method. * @param cl the class containing the method */ public abstract MethodHandle readObjectForSerialization(Class cl) throws NoSuchMethodException, IllegalAccessException; /** * Returns a method handle to allow invocation of the specified class's readResolve method. * @param cl the class containing the method */ public abstract MethodHandle readResolveForSerialization(Class cl); /** * Returns a method handle to allow invocation of the specified class's writeReplace method. * @param cl the class containing the method */ public abstract MethodHandle writeReplaceForSerialization(Class cl); /** * Return a new OptionalDataException instance. * @return a new OptionalDataException instance */ public abstract OptionalDataException newOptionalDataExceptionForSerialization(boolean bool); /** * Returns the specified field after calling setAccessible, if it is accessible from the specified class. * @param field the field to make accessible * @param callingClass the class which wants to access it. * @return the original field, rendered accessible, or null. */ public Field toAccessibleField(Field field, Class callingClass) { field.setAccessible(true); return field; } /** * Returns the specified method after calling setAccessible, if it is accessible from the specified class. * @param method the method to make accessible * @param callingClass the class which wants to access it. * @return the original method, rendered accessible, or null. */ public Method toAccessibleMethod(Method method, Class callingClass) { method.setAccessible(true); return method; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy