| /* |
| * Copyright (c) 2004, 2010, 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 sun.corba ; |
| |
| import java.lang.reflect.Field ; |
| import java.lang.reflect.Method ; |
| import java.lang.reflect.Constructor ; |
| import java.lang.reflect.InvocationTargetException ; |
| |
| import java.io.ObjectInputStream ; |
| |
| import java.security.AccessController; |
| import java.security.Permission; |
| import java.security.PrivilegedAction; |
| |
| import sun.misc.Unsafe ; |
| import sun.reflect.ReflectionFactory ; |
| |
| /** This class provides the methods for fundamental JVM operations |
| * needed in the ORB that are not part of the public Java API. This includes: |
| * <ul> |
| * <li>throwException, which can throw undeclared checked exceptions. |
| * This is needed to handle throwing arbitrary exceptions across a standardized OMG interface that (incorrectly) does not specify appropriate exceptions.</li> |
| * <li>putXXX/getXXX methods that allow unchecked access to fields of objects. |
| * This is used for setting uninitialzed non-static final fields (which is |
| * impossible with reflection) and for speed.</li> |
| * <li>objectFieldOffset to obtain the field offsets for use in the putXXX/getXXX methods</li> |
| * <li>newConstructorForSerialization to get the special constructor required for a |
| * Serializable class</li> |
| * <li>latestUserDefinedLoader to get the latest user defined class loader from |
| * the call stack as required by the RMI-IIOP specification (really from the |
| * JDK 1.1 days)</li> |
| * </ul> |
| * The code that calls Bridge.get() must have the following Permissions: |
| * <ul> |
| * <li>RuntimePermission "reflectionFactoryAccess"</li> |
| * <li>BridgePermission "getBridge"</li> |
| * <li>ReflectPermission "suppressAccessChecks"</li> |
| * </ul> |
| * <p> |
| * All of these permissions are required to obtain and correctly initialize |
| * the instance of Bridge. No security checks are performed on calls |
| * made to Bridge instance methods, so access to the Bridge instance |
| * must be protected. |
| * <p> |
| * This class is a singleton (per ClassLoader of course). Access to the |
| * instance is obtained through the Bridge.get() method. |
| */ |
| public final class Bridge |
| { |
| private static final Class[] NO_ARGS = new Class[] {}; |
| private static final Permission getBridgePermission = |
| new BridgePermission( "getBridge" ) ; |
| private static Bridge bridge = null ; |
| |
| // latestUserDefinedLoader() is a private static method |
| // in ObjectInputStream in JDK 1.3 through 1.5. |
| // We use reflection in a doPrivileged block to get a |
| // Method reference and make it accessible. |
| private final Method latestUserDefinedLoaderMethod ; |
| private final Unsafe unsafe ; |
| private final ReflectionFactory reflectionFactory ; |
| |
| private Method getLatestUserDefinedLoaderMethod() |
| { |
| return (Method) AccessController.doPrivileged( |
| new PrivilegedAction() |
| { |
| public Object run() |
| { |
| Method result = null; |
| |
| try { |
| Class io = ObjectInputStream.class; |
| result = io.getDeclaredMethod( |
| "latestUserDefinedLoader", NO_ARGS); |
| result.setAccessible(true); |
| } catch (NoSuchMethodException nsme) { |
| Error err = new Error( "java.io.ObjectInputStream" + |
| " latestUserDefinedLoader " + nsme ); |
| err.initCause(nsme) ; |
| throw err ; |
| } |
| |
| return result; |
| } |
| } |
| ); |
| } |
| |
| private Unsafe getUnsafe() { |
| Field fld = (Field)AccessController.doPrivileged( |
| new PrivilegedAction() |
| { |
| public Object run() |
| { |
| Field fld = null ; |
| |
| try { |
| Class unsafeClass = sun.misc.Unsafe.class ; |
| fld = unsafeClass.getDeclaredField( "theUnsafe" ) ; |
| fld.setAccessible( true ) ; |
| return fld ; |
| } catch (NoSuchFieldException exc) { |
| Error err = new Error( "Could not access Unsafe" ) ; |
| err.initCause( exc ) ; |
| throw err ; |
| } |
| } |
| } |
| ) ; |
| |
| Unsafe unsafe = null; |
| |
| try { |
| unsafe = (Unsafe)(fld.get( null )) ; |
| } catch (Throwable t) { |
| Error err = new Error( "Could not access Unsafe" ) ; |
| err.initCause( t ) ; |
| throw err ; |
| } |
| |
| return unsafe ; |
| } |
| |
| |
| private Bridge() |
| { |
| latestUserDefinedLoaderMethod = getLatestUserDefinedLoaderMethod(); |
| unsafe = getUnsafe() ; |
| reflectionFactory = (ReflectionFactory)AccessController.doPrivileged( |
| new ReflectionFactory.GetReflectionFactoryAction()); |
| } |
| |
| /** Fetch the Bridge singleton. This requires the following |
| * permissions: |
| * <ul> |
| * <li>RuntimePermission "reflectionFactoryAccess"</li> |
| * <li>BridgePermission "getBridge"</li> |
| * <li>ReflectPermission "suppressAccessChecks"</li> |
| * </ul> |
| * @return The singleton instance of the Bridge class |
| * @throws SecurityException if the caller does not have the |
| * required permissions and the caller has a non-null security manager. |
| */ |
| public static final synchronized Bridge get() |
| { |
| SecurityManager sman = System.getSecurityManager() ; |
| if (sman != null) |
| sman.checkPermission( getBridgePermission ) ; |
| |
| if (bridge == null) { |
| bridge = new Bridge() ; |
| } |
| |
| return bridge ; |
| } |
| |
| /** Obtain the latest user defined ClassLoader from the call stack. |
| * This is required by the RMI-IIOP specification. |
| */ |
| public final ClassLoader getLatestUserDefinedLoader() |
| { |
| try { |
| // Invoke the ObjectInputStream.latestUserDefinedLoader method |
| return (ClassLoader)latestUserDefinedLoaderMethod.invoke(null, |
| (Object[])NO_ARGS); |
| } catch (InvocationTargetException ite) { |
| Error err = new Error( |
| "sun.corba.Bridge.latestUserDefinedLoader: " + ite ) ; |
| err.initCause( ite ) ; |
| throw err ; |
| } catch (IllegalAccessException iae) { |
| Error err = new Error( |
| "sun.corba.Bridge.latestUserDefinedLoader: " + iae ) ; |
| err.initCause( iae ) ; |
| throw err ; |
| } |
| } |
| |
| /** |
| * Fetches a field element within the given |
| * object <code>o</code> 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 <code>o</code> |
| * 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. |
| * <p> |
| * 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. |
| * <p> |
| * The field must be of the same type as the method |
| * parameter <code>x</code>. |
| * |
| * @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) |
| { |
| unsafe.putInt( o, offset, x ) ; |
| } |
| |
| /** |
| * @see #getInt(Object, long) |
| */ |
| public final Object getObject(Object o, long offset) |
| { |
| return unsafe.getObject( o, offset ) ; |
| } |
| |
| /** |
| * @see #putInt(Object, long, int) |
| */ |
| public final void putObject(Object o, long offset, Object x) |
| { |
| 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) |
| { |
| 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) |
| { |
| 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) |
| { |
| 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) |
| { |
| 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) |
| { |
| 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) |
| { |
| 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) |
| { |
| unsafe.putDouble( o, offset, x ) ; |
| } |
| |
| /** |
| * This constant differs from all results that will ever be returned from |
| * {@link #objectFieldOffset}. |
| */ |
| public static final long INVALID_FIELD_OFFSET = -1; |
| |
| /** |
| * Returns the offset of a non-static field. |
| */ |
| public final long objectFieldOffset(Field f) |
| { |
| return unsafe.objectFieldOffset( f ) ; |
| } |
| |
| /** Throw the exception. |
| * The exception may be an undeclared checked exception. |
| */ |
| public final void throwException(Throwable ee) |
| { |
| unsafe.throwException( ee ) ; |
| } |
| |
| /** Obtain a constructor for Class cl using constructor cons which |
| * may be the constructor defined in a superclass of cl. This is |
| * used to create a constructor for Serializable classes that |
| * constructs an instance of the Serializable class using the |
| * no args constructor of the first non-Serializable superclass |
| * of the Serializable class. |
| */ |
| public final Constructor newConstructorForSerialization( Class cl, |
| Constructor cons ) |
| { |
| return reflectionFactory.newConstructorForSerialization( cl, cons ) ; |
| } |
| } |