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