Bridge.java revision 724:e7ddf972e152
1/*
2 * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.  Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26package sun.corba ;
27
28import java.lang.reflect.Field ;
29import java.lang.reflect.Method ;
30import java.lang.reflect.Constructor ;
31import java.lang.reflect.InvocationTargetException ;
32
33import java.io.ObjectInputStream ;
34
35import java.security.AccessController;
36import java.security.Permission;
37import java.security.PrivilegedAction;
38
39import jdk.internal.misc.Unsafe ;
40import sun.reflect.ReflectionFactory ;
41
42/** This class provides the methods for fundamental JVM operations
43 * needed in the ORB that are not part of the public Java API.  This includes:
44 * <ul>
45 * <li>throwException, which can throw undeclared checked exceptions.
46 * This is needed to handle throwing arbitrary exceptions across a standardized OMG interface that (incorrectly) does not specify appropriate exceptions.</li>
47 * <li>putXXX/getXXX methods that allow unchecked access to fields of objects.
48 * This is used for setting uninitialzed non-static final fields (which is
49 * impossible with reflection) and for speed.</li>
50 * <li>objectFieldOffset to obtain the field offsets for use in the putXXX/getXXX methods</li>
51 * <li>newConstructorForSerialization to get the special constructor required for a
52 * Serializable class</li>
53 * <li>latestUserDefinedLoader to get the latest user defined class loader from
54 * the call stack as required by the RMI-IIOP specification (really from the
55 * JDK 1.1 days)</li>
56 * </ul>
57 * The code that calls Bridge.get() must have the following Permissions:
58 * <ul>
59 * <li>RuntimePermission "reflectionFactoryAccess"</li>
60 * <li>BridgePermission "getBridge"</li>
61 * <li>ReflectPermission "suppressAccessChecks"</li>
62 * </ul>
63 * <p>
64 * All of these permissions are required to obtain and correctly initialize
65 * the instance of Bridge.  No security checks are performed on calls
66 * made to Bridge instance methods, so access to the Bridge instance
67 * must be protected.
68 * <p>
69 * This class is a singleton (per ClassLoader of course).  Access to the
70 * instance is obtained through the Bridge.get() method.
71 */
72public final class Bridge
73{
74    private static final Class[] NO_ARGS = new Class[] {};
75    private static final Permission getBridgePermission =
76        new BridgePermission( "getBridge" ) ;
77    private static Bridge bridge = null ;
78
79    // latestUserDefinedLoader() is a private static method
80    // in ObjectInputStream in JDK 1.3 through 1.5.
81    // We use reflection in a doPrivileged block to get a
82    // Method reference and make it accessible.
83    private final Method latestUserDefinedLoaderMethod ;
84    private final Unsafe unsafe ;
85    private final ReflectionFactory reflectionFactory ;
86
87    private Method getLatestUserDefinedLoaderMethod()
88    {
89        return (Method) AccessController.doPrivileged(
90            new PrivilegedAction()
91            {
92                public Object run()
93                {
94                    Method result = null;
95
96                    try {
97                        Class io = ObjectInputStream.class;
98                        result = io.getDeclaredMethod(
99                            "latestUserDefinedLoader", NO_ARGS);
100                        result.setAccessible(true);
101                    } catch (NoSuchMethodException nsme) {
102                        Error err = new Error( "java.io.ObjectInputStream" +
103                            " latestUserDefinedLoader " + nsme );
104                        err.initCause(nsme) ;
105                        throw err ;
106                    }
107
108                    return result;
109                }
110            }
111        );
112    }
113
114    private Unsafe getUnsafe() {
115        Field fld = (Field)AccessController.doPrivileged(
116            new PrivilegedAction()
117            {
118                public Object run()
119                {
120                    Field fld = null ;
121
122                    try {
123                        Class unsafeClass = jdk.internal.misc.Unsafe.class ;
124                        fld = unsafeClass.getDeclaredField( "theUnsafe" ) ;
125                        fld.setAccessible( true ) ;
126                        return fld ;
127                    } catch (NoSuchFieldException exc) {
128                        Error err = new Error( "Could not access Unsafe" ) ;
129                        err.initCause( exc ) ;
130                        throw err ;
131                    }
132                }
133            }
134        ) ;
135
136        Unsafe unsafe = null;
137
138        try {
139            unsafe = (Unsafe)(fld.get( null )) ;
140        } catch (Throwable t) {
141            Error err = new Error( "Could not access Unsafe" ) ;
142            err.initCause( t ) ;
143            throw err ;
144        }
145
146        return unsafe ;
147    }
148
149
150    private Bridge()
151    {
152        latestUserDefinedLoaderMethod = getLatestUserDefinedLoaderMethod();
153        unsafe = getUnsafe() ;
154        reflectionFactory = (ReflectionFactory)AccessController.doPrivileged(
155            new ReflectionFactory.GetReflectionFactoryAction());
156    }
157
158    /** Fetch the Bridge singleton.  This requires the following
159     * permissions:
160     * <ul>
161     * <li>RuntimePermission "reflectionFactoryAccess"</li>
162     * <li>BridgePermission "getBridge"</li>
163     * <li>ReflectPermission "suppressAccessChecks"</li>
164     * </ul>
165     * @return The singleton instance of the Bridge class
166     * @throws SecurityException if the caller does not have the
167     * required permissions and the caller has a non-null security manager.
168     */
169    public static final synchronized Bridge get()
170    {
171        SecurityManager sman = System.getSecurityManager() ;
172        if (sman != null)
173            sman.checkPermission( getBridgePermission ) ;
174
175        if (bridge == null) {
176            bridge = new Bridge() ;
177        }
178
179        return bridge ;
180    }
181
182    /** Obtain the latest user defined ClassLoader from the call stack.
183     * This is required by the RMI-IIOP specification.
184     */
185    public final ClassLoader getLatestUserDefinedLoader()
186    {
187        try {
188            // Invoke the ObjectInputStream.latestUserDefinedLoader method
189            return (ClassLoader)latestUserDefinedLoaderMethod.invoke(null,
190                                                                     (Object[])NO_ARGS);
191        } catch (InvocationTargetException ite) {
192            Error err = new Error(
193                "sun.corba.Bridge.latestUserDefinedLoader: " + ite ) ;
194            err.initCause( ite ) ;
195            throw err ;
196        } catch (IllegalAccessException iae) {
197            Error err = new Error(
198                "sun.corba.Bridge.latestUserDefinedLoader: " + iae ) ;
199            err.initCause( iae ) ;
200            throw err ;
201        }
202    }
203
204    /**
205     * Fetches a field element within the given
206     * object <code>o</code> at the given offset.
207     * The result is undefined unless the offset was obtained from
208     * {@link #objectFieldOffset} on the {@link java.lang.reflect.Field}
209     * of some Java field and the object referred to by <code>o</code>
210     * is of a class compatible with that field's class.
211     * @param o Java heap object in which the field from which the offset
212     * was obtained resides
213     * @param offset indication of where the field resides in a Java heap
214     *        object
215     * @return the value fetched from the indicated Java field
216     * @throws RuntimeException No defined exceptions are thrown, not even
217     *         {@link NullPointerException}
218     */
219    public final int getInt(Object o, long offset)
220    {
221        return unsafe.getInt( o, offset ) ;
222    }
223
224    /**
225     * Stores a value into a given Java field.
226     * <p>
227     * The first two parameters are interpreted exactly as with
228     * {@link #getInt(Object, long)} to refer to a specific
229     * Java field.  The given value is stored into that field.
230     * <p>
231     * The field must be of the same type as the method
232     * parameter <code>x</code>.
233     *
234     * @param o Java heap object in which the field resides, if any, else
235     *        null
236     * @param offset indication of where the field resides in a Java heap
237     *        object.
238     * @param x the value to store into the indicated Java field
239     * @throws RuntimeException No defined exceptions are thrown, not even
240     *         {@link NullPointerException}
241     */
242    public final void putInt(Object o, long offset, int x)
243    {
244        unsafe.putInt( o, offset, x ) ;
245    }
246
247    /**
248     * @see #getInt(Object, long)
249     */
250    public final Object getObject(Object o, long offset)
251    {
252        return unsafe.getObject( o, offset ) ;
253    }
254
255    /**
256     * @see #putInt(Object, long, int)
257     */
258    public final void putObject(Object o, long offset, Object x)
259    {
260        unsafe.putObject( o, offset, x ) ;
261    }
262
263    /** @see #getInt(Object, long) */
264    public final boolean getBoolean(Object o, long offset)
265    {
266        return unsafe.getBoolean( o, offset ) ;
267    }
268    /** @see #putInt(Object, long, int) */
269    public final void    putBoolean(Object o, long offset, boolean x)
270    {
271        unsafe.putBoolean( o, offset, x ) ;
272    }
273    /** @see #getInt(Object, long) */
274    public final byte    getByte(Object o, long offset)
275    {
276        return unsafe.getByte( o, offset ) ;
277    }
278    /** @see #putInt(Object, long, int) */
279    public final void    putByte(Object o, long offset, byte x)
280    {
281        unsafe.putByte( o, offset, x ) ;
282    }
283    /** @see #getInt(Object, long) */
284    public final short   getShort(Object o, long offset)
285    {
286        return unsafe.getShort( o, offset ) ;
287    }
288    /** @see #putInt(Object, long, int) */
289    public final void    putShort(Object o, long offset, short x)
290    {
291        unsafe.putShort( o, offset, x ) ;
292    }
293    /** @see #getInt(Object, long) */
294    public final char    getChar(Object o, long offset)
295    {
296        return unsafe.getChar( o, offset ) ;
297    }
298    /** @see #putInt(Object, long, int) */
299    public final void    putChar(Object o, long offset, char x)
300    {
301        unsafe.putChar( o, offset, x ) ;
302    }
303    /** @see #getInt(Object, long) */
304    public final long    getLong(Object o, long offset)
305    {
306        return unsafe.getLong( o, offset ) ;
307    }
308    /** @see #putInt(Object, long, int) */
309    public final void    putLong(Object o, long offset, long x)
310    {
311        unsafe.putLong( o, offset, x ) ;
312    }
313    /** @see #getInt(Object, long) */
314    public final float   getFloat(Object o, long offset)
315    {
316        return unsafe.getFloat( o, offset ) ;
317    }
318    /** @see #putInt(Object, long, int) */
319    public final void    putFloat(Object o, long offset, float x)
320    {
321        unsafe.putFloat( o, offset, x ) ;
322    }
323    /** @see #getInt(Object, long) */
324    public final double  getDouble(Object o, long offset)
325    {
326        return unsafe.getDouble( o, offset ) ;
327    }
328    /** @see #putInt(Object, long, int) */
329    public final void    putDouble(Object o, long offset, double x)
330    {
331        unsafe.putDouble( o, offset, x ) ;
332    }
333
334    /**
335     * This constant differs from all results that will ever be returned from
336     * {@link #objectFieldOffset}.
337     */
338    public static final long INVALID_FIELD_OFFSET   = -1;
339
340    /**
341     * Returns the offset of a non-static field.
342     */
343    public final long objectFieldOffset(Field f)
344    {
345        return unsafe.objectFieldOffset( f ) ;
346    }
347
348    /** Throw the exception.
349     * The exception may be an undeclared checked exception.
350     */
351    public final void throwException(Throwable ee)
352    {
353        unsafe.throwException( ee ) ;
354    }
355
356    /** Obtain a constructor for Class cl using constructor cons which
357     * may be the constructor defined in a superclass of cl.  This is
358     * used to create a constructor for Serializable classes that
359     * constructs an instance of the Serializable class using the
360     * no args constructor of the first non-Serializable superclass
361     * of the Serializable class.
362     */
363    public final Constructor newConstructorForSerialization( Class cl,
364        Constructor cons )
365    {
366        return reflectionFactory.newConstructorForSerialization( cl, cons ) ;
367    }
368}
369