Bridge.java revision 851:31dddeed0943
1/*
2 * Copyright (c) 2004, 2016, 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.io.OptionalDataException;
29import java.lang.invoke.MethodHandle;
30import java.lang.reflect.Field ;
31import java.lang.reflect.Constructor ;
32import java.lang.StackWalker;
33import java.lang.StackWalker.StackFrame;
34import java.util.Optional;
35import java.util.stream.Stream;
36
37import java.security.AccessController;
38import java.security.Permission;
39import java.security.PrivilegedAction;
40
41import sun.misc.Unsafe;
42import sun.reflect.ReflectionFactory;
43
44/** This class provides the methods for fundamental JVM operations
45 * needed in the ORB that are not part of the public Java API.  This includes:
46 * <ul>
47 * <li>throwException, which can throw undeclared checked exceptions.
48 * This is needed to handle throwing arbitrary exceptions across a standardized
49 * OMG interface that (incorrectly) does not specify appropriate exceptions.</li>
50 * <li>putXXX/getXXX methods that allow unchecked access to fields of objects.
51 * This is used for setting uninitialzed non-static final fields (which is
52 * impossible with reflection) and for speed.</li>
53 * <li>objectFieldOffset to obtain the field offsets for use in the putXXX/getXXX methods</li>
54 * <li>newConstructorForSerialization to get the special constructor required for a
55 * Serializable class</li>
56 * <li>latestUserDefinedLoader to get the latest user defined class loader from
57 * the call stack as required by the RMI-IIOP specification (really from the
58 * JDK 1.1 days)</li>
59 * </ul>
60 * The code that calls Bridge.get() must have the following Permissions:
61 * <ul>
62 * <li>BridgePermission "getBridge"</li>
63 * <li>ReflectPermission "suppressAccessChecks"</li>
64 * <li>RuntimePermission "getStackWalkerWithClassReference"</li>
65 * <li>RuntimePermission "reflectionFactoryAccess"</li>
66 * </ul>
67 * <p>
68 * All of these permissions are required to obtain and correctly initialize
69 * the instance of Bridge.  No security checks are performed on calls
70 * made to Bridge instance methods, so access to the Bridge instance
71 * must be protected.
72 * <p>
73 * This class is a singleton (per ClassLoader of course).  Access to the
74 * instance is obtained through the Bridge.get() method.
75 */
76public final class Bridge
77{
78    private static final Permission getBridgePermission =
79            new BridgePermission("getBridge");
80    private static Bridge bridge = null ;
81
82    /** Access to Unsafe to read/write fields. */
83    private static final Unsafe unsafe = AccessController.doPrivileged(
84            (PrivilegedAction<Unsafe>)() -> {
85                try {
86                    Field field = Unsafe.class.getDeclaredField("theUnsafe");
87                    field.setAccessible(true);
88                    return (Unsafe)field.get(null);
89
90                } catch (NoSuchFieldException |IllegalAccessException ex) {
91                    throw new InternalError("Unsafe.theUnsafe field not available", ex);
92                }
93            }
94    ) ;
95
96    private final ReflectionFactory reflectionFactory ;
97    private final StackWalker stackWalker;
98
99    private Bridge() {
100        reflectionFactory = ReflectionFactory.getReflectionFactory();
101        stackWalker  = StackWalker.getInstance(
102                            StackWalker.Option.RETAIN_CLASS_REFERENCE);
103    }
104
105    /** Fetch the Bridge singleton.  This requires the following
106     * permissions:
107     * <ul>
108     * <li>BridgePermission "getBridge"</li>
109     * <li>ReflectPermission "suppressAccessChecks"</li>
110     * <li>RuntimePermission "getStackWalkerWithClassReference"</li>
111     * <li>RuntimePermission "reflectionFactoryAccess"</li>
112     * </ul>
113     * @return The singleton instance of the Bridge class
114     * @throws SecurityException if the caller does not have the
115     * required permissions and the caller has a non-null security manager.
116     */
117    public static final synchronized Bridge get()
118    {
119        SecurityManager sman = System.getSecurityManager() ;
120        if (sman != null)
121            sman.checkPermission( getBridgePermission ) ;
122
123        if (bridge == null) {
124            bridge = new Bridge() ;
125        }
126
127        return bridge ;
128    }
129
130    /** Returns true if the loader that loaded the frame's declaring class
131     * is a user loader (if it is not the platform class loader or one of
132     * its ancestor).
133     */
134    private boolean isUserLoader(StackFrame sf) {
135        ClassLoader cl = sf.getDeclaringClass().getClassLoader();
136        if (cl == null) return false;
137        ClassLoader p = ClassLoader.getPlatformClassLoader();
138        while (cl != p && p != null) p = p.getParent();
139        return cl != p;
140    }
141
142    private Optional<StackFrame> getLatestUserDefinedLoaderFrame(Stream<StackFrame> stream) {
143        return stream.filter(this::isUserLoader).findFirst();
144    }
145
146
147    /** Obtain the latest user defined ClassLoader from the call stack.
148     * This is required by the RMI-IIOP specification.
149     */
150    public final ClassLoader getLatestUserDefinedLoader() {
151        // requires getClassLoader permission => needs doPrivileged.
152        PrivilegedAction<ClassLoader> pa = () ->
153            stackWalker.walk(this::getLatestUserDefinedLoaderFrame)
154                .map(sf -> sf.getDeclaringClass().getClassLoader())
155                .orElseGet(() -> ClassLoader.getPlatformClassLoader());
156        return AccessController.doPrivileged(pa);
157    }
158
159    /**
160     * Fetches a field element within the given
161     * object <code>o</code> at the given offset.
162     * The result is undefined unless the offset was obtained from
163     * {@link #objectFieldOffset} on the {@link java.lang.reflect.Field}
164     * of some Java field and the object referred to by <code>o</code>
165     * is of a class compatible with that field's class.
166     * @param o Java heap object in which the field from which the offset
167     * was obtained resides
168     * @param offset indication of where the field resides in a Java heap
169     *        object
170     * @return the value fetched from the indicated Java field
171     * @throws RuntimeException No defined exceptions are thrown, not even
172     *         {@link NullPointerException}
173     */
174    public final int getInt(Object o, long offset)
175    {
176        return unsafe.getInt( o, offset ) ;
177    }
178
179    /**
180     * Stores a value into a given Java field.
181     * <p>
182     * The first two parameters are interpreted exactly as with
183     * {@link #getInt(Object, long)} to refer to a specific
184     * Java field.  The given value is stored into that field.
185     * <p>
186     * The field must be of the same type as the method
187     * parameter <code>x</code>.
188     *
189     * @param o Java heap object in which the field resides, if any, else
190     *        null
191     * @param offset indication of where the field resides in a Java heap
192     *        object.
193     * @param x the value to store into the indicated Java field
194     * @throws RuntimeException No defined exceptions are thrown, not even
195     *         {@link NullPointerException}
196     */
197    public final void putInt(Object o, long offset, int x)
198    {
199        unsafe.putInt( o, offset, x ) ;
200    }
201
202    /**
203     * @see #getInt(Object, long)
204     */
205    public final Object getObject(Object o, long offset)
206    {
207        return unsafe.getObject( o, offset ) ;
208    }
209
210    /**
211     * @see #putInt(Object, long, int)
212     */
213    public final void putObject(Object o, long offset, Object x)
214    {
215        unsafe.putObject( o, offset, x ) ;
216    }
217
218    /** @see #getInt(Object, long) */
219    public final boolean getBoolean(Object o, long offset)
220    {
221        return unsafe.getBoolean( o, offset ) ;
222    }
223    /** @see #putInt(Object, long, int) */
224    public final void    putBoolean(Object o, long offset, boolean x)
225    {
226        unsafe.putBoolean( o, offset, x ) ;
227    }
228    /** @see #getInt(Object, long) */
229    public final byte    getByte(Object o, long offset)
230    {
231        return unsafe.getByte( o, offset ) ;
232    }
233    /** @see #putInt(Object, long, int) */
234    public final void    putByte(Object o, long offset, byte x)
235    {
236        unsafe.putByte( o, offset, x ) ;
237    }
238    /** @see #getInt(Object, long) */
239    public final short   getShort(Object o, long offset)
240    {
241        return unsafe.getShort( o, offset ) ;
242    }
243    /** @see #putInt(Object, long, int) */
244    public final void    putShort(Object o, long offset, short x)
245    {
246        unsafe.putShort( o, offset, x ) ;
247    }
248    /** @see #getInt(Object, long) */
249    public final char    getChar(Object o, long offset)
250    {
251        return unsafe.getChar( o, offset ) ;
252    }
253    /** @see #putInt(Object, long, int) */
254    public final void    putChar(Object o, long offset, char x)
255    {
256        unsafe.putChar( o, offset, x ) ;
257    }
258    /** @see #getInt(Object, long) */
259    public final long    getLong(Object o, long offset)
260    {
261        return unsafe.getLong( o, offset ) ;
262    }
263    /** @see #putInt(Object, long, int) */
264    public final void    putLong(Object o, long offset, long x)
265    {
266        unsafe.putLong( o, offset, x ) ;
267    }
268    /** @see #getInt(Object, long) */
269    public final float   getFloat(Object o, long offset)
270    {
271        return unsafe.getFloat( o, offset ) ;
272    }
273    /** @see #putInt(Object, long, int) */
274    public final void    putFloat(Object o, long offset, float x)
275    {
276        unsafe.putFloat( o, offset, x ) ;
277    }
278    /** @see #getInt(Object, long) */
279    public final double  getDouble(Object o, long offset)
280    {
281        return unsafe.getDouble( o, offset ) ;
282    }
283    /** @see #putInt(Object, long, int) */
284    public final void    putDouble(Object o, long offset, double x)
285    {
286        unsafe.putDouble( o, offset, x ) ;
287    }
288
289    /**
290     * This constant differs from all results that will ever be returned from
291     * {@link #objectFieldOffset}.
292     */
293    public static final long INVALID_FIELD_OFFSET   = -1;
294
295    /**
296     * Returns the offset of a non-static field.
297     */
298    public final long objectFieldOffset(Field f)
299    {
300        return unsafe.objectFieldOffset( f ) ;
301    }
302
303    /**
304     * Returns the offset of a static field.
305     */
306    public final long staticFieldOffset(Field f)
307    {
308        return unsafe.staticFieldOffset( f ) ;
309    }
310
311    /**
312     * Ensure that the class has been initalized.
313     * @param cl the class to ensure is initialized
314     */
315    public final void ensureClassInitialized(Class<?> cl) {
316        unsafe.ensureClassInitialized(cl);
317    }
318
319
320    /** Throw the exception.
321     * The exception may be an undeclared checked exception.
322     */
323    public final void throwException(Throwable ee)
324    {
325        unsafe.throwException( ee ) ;
326    }
327
328    /**
329     * Obtain a constructor for Class cl.
330     * This is used to create a constructor for Serializable classes that
331     * construct an instance of the Serializable class using the
332     * no args constructor of the first non-Serializable superclass
333     * of the Serializable class.
334     */
335    public final Constructor<?> newConstructorForSerialization( Class<?> cl ) {
336        return reflectionFactory.newConstructorForSerialization( cl ) ;
337    }
338
339    public final Constructor<?> newConstructorForExternalization(Class<?> cl) {
340        return reflectionFactory.newConstructorForExternalization( cl ) ;
341    }
342
343    /**
344     * Returns true if the given class defines a static initializer method,
345     * false otherwise.
346     */
347    public final boolean hasStaticInitializerForSerialization(Class<?> cl) {
348        return reflectionFactory.hasStaticInitializerForSerialization(cl);
349    }
350
351    public final MethodHandle writeObjectForSerialization(Class<?> cl) {
352        return reflectionFactory.writeObjectForSerialization(cl);
353    }
354
355    public final MethodHandle readObjectForSerialization(Class<?> cl) {
356        return reflectionFactory.readObjectForSerialization(cl);
357    }
358
359    public final MethodHandle readObjectNoDataForSerialization(Class<?> cl) {
360        return reflectionFactory.readObjectNoDataForSerialization(cl);
361    }
362
363    public final MethodHandle readResolveForSerialization(Class<?> cl) {
364        return reflectionFactory.readResolveForSerialization(cl);
365    }
366
367    public final MethodHandle writeReplaceForSerialization(Class<?> cl) {
368        return reflectionFactory.writeReplaceForSerialization(cl);
369    }
370
371    /**
372     * Return a new OptionalDataException instance.
373     * @return a new OptionalDataException instance
374     */
375    public final OptionalDataException newOptionalDataExceptionForSerialization(boolean bool) {
376        return reflectionFactory.newOptionalDataExceptionForSerialization(bool);
377    }
378
379}
380