1 /* 2 * Copyright (C) 2007 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package sun.misc; 18 19 import dalvik.system.VMStack; 20 import java.lang.reflect.Field; 21 import java.lang.reflect.Modifier; 22 23 /** 24 * The package name notwithstanding, this class is the quasi-standard 25 * way for Java code to gain access to and use functionality which, 26 * when unsupervised, would allow one to break the pointer/type safety 27 * of Java. 28 */ 29 public final class Unsafe { 30 /** Traditional dalvik name. */ 31 private static final Unsafe THE_ONE = new Unsafe(); 32 /** Traditional RI name. */ 33 private static final Unsafe theUnsafe = THE_ONE; 34 35 /** 36 * This class is only privately instantiable. 37 */ Unsafe()38 private Unsafe() {} 39 40 /** 41 * Gets the unique instance of this class. This is only allowed in 42 * very limited situations. 43 */ getUnsafe()44 public static Unsafe getUnsafe() { 45 /* 46 * Only code on the bootclasspath is allowed to get at the 47 * Unsafe instance. 48 */ 49 ClassLoader calling = VMStack.getCallingClassLoader(); 50 if ((calling != null) && (calling != Unsafe.class.getClassLoader())) { 51 throw new SecurityException("Unsafe access denied"); 52 } 53 54 return THE_ONE; 55 } 56 57 /** 58 * Gets the raw byte offset from the start of an object's memory to 59 * the memory used to store the indicated instance field. 60 * 61 * @param field non-null; the field in question, which must be an 62 * instance field 63 * @return the offset to the field 64 */ objectFieldOffset(Field field)65 public long objectFieldOffset(Field field) { 66 if (Modifier.isStatic(field.getModifiers())) { 67 throw new IllegalArgumentException("valid for instance fields only"); 68 } 69 return field.getOffset(); 70 } 71 72 /** 73 * Gets the offset from the start of an array object's memory to 74 * the memory used to store its initial (zeroeth) element. 75 * 76 * @param clazz non-null; class in question; must be an array class 77 * @return the offset to the initial element 78 */ arrayBaseOffset(Class clazz)79 public int arrayBaseOffset(Class clazz) { 80 Class<?> component = clazz.getComponentType(); 81 if (component == null) { 82 throw new IllegalArgumentException("Valid for array classes only: " + clazz); 83 } 84 return getArrayBaseOffsetForComponentType(component); 85 } 86 87 /** 88 * Gets the size of each element of the given array class. 89 * 90 * @param clazz non-null; class in question; must be an array class 91 * @return > 0; the size of each element of the array 92 */ arrayIndexScale(Class clazz)93 public int arrayIndexScale(Class clazz) { 94 Class<?> component = clazz.getComponentType(); 95 if (component == null) { 96 throw new IllegalArgumentException("Valid for array classes only: " + clazz); 97 } 98 return getArrayIndexScaleForComponentType(component); 99 } 100 getArrayBaseOffsetForComponentType(Class component_class)101 private static native int getArrayBaseOffsetForComponentType(Class component_class); getArrayIndexScaleForComponentType(Class component_class)102 private static native int getArrayIndexScaleForComponentType(Class component_class); 103 104 /** 105 * Performs a compare-and-set operation on an <code>int</code> 106 * field within the given object. 107 * 108 * @param obj non-null; object containing the field 109 * @param offset offset to the field within <code>obj</code> 110 * @param expectedValue expected value of the field 111 * @param newValue new value to store in the field if the contents are 112 * as expected 113 * @return <code>true</code> if the new value was in fact stored, and 114 * <code>false</code> if not 115 */ compareAndSwapInt(Object obj, long offset, int expectedValue, int newValue)116 public native boolean compareAndSwapInt(Object obj, long offset, 117 int expectedValue, int newValue); 118 119 /** 120 * Performs a compare-and-set operation on a <code>long</code> 121 * field within the given object. 122 * 123 * @param obj non-null; object containing the field 124 * @param offset offset to the field within <code>obj</code> 125 * @param expectedValue expected value of the field 126 * @param newValue new value to store in the field if the contents are 127 * as expected 128 * @return <code>true</code> if the new value was in fact stored, and 129 * <code>false</code> if not 130 */ compareAndSwapLong(Object obj, long offset, long expectedValue, long newValue)131 public native boolean compareAndSwapLong(Object obj, long offset, 132 long expectedValue, long newValue); 133 134 /** 135 * Performs a compare-and-set operation on an <code>Object</code> 136 * field (that is, a reference field) within the given object. 137 * 138 * @param obj non-null; object containing the field 139 * @param offset offset to the field within <code>obj</code> 140 * @param expectedValue expected value of the field 141 * @param newValue new value to store in the field if the contents are 142 * as expected 143 * @return <code>true</code> if the new value was in fact stored, and 144 * <code>false</code> if not 145 */ compareAndSwapObject(Object obj, long offset, Object expectedValue, Object newValue)146 public native boolean compareAndSwapObject(Object obj, long offset, 147 Object expectedValue, Object newValue); 148 149 /** 150 * Gets an <code>int</code> field from the given object, 151 * using <code>volatile</code> semantics. 152 * 153 * @param obj non-null; object containing the field 154 * @param offset offset to the field within <code>obj</code> 155 * @return the retrieved value 156 */ getIntVolatile(Object obj, long offset)157 public native int getIntVolatile(Object obj, long offset); 158 159 /** 160 * Stores an <code>int</code> field into the given object, 161 * using <code>volatile</code> semantics. 162 * 163 * @param obj non-null; object containing the field 164 * @param offset offset to the field within <code>obj</code> 165 * @param newValue the value to store 166 */ putIntVolatile(Object obj, long offset, int newValue)167 public native void putIntVolatile(Object obj, long offset, int newValue); 168 169 /** 170 * Gets a <code>long</code> field from the given object, 171 * using <code>volatile</code> semantics. 172 * 173 * @param obj non-null; object containing the field 174 * @param offset offset to the field within <code>obj</code> 175 * @return the retrieved value 176 */ getLongVolatile(Object obj, long offset)177 public native long getLongVolatile(Object obj, long offset); 178 179 /** 180 * Stores a <code>long</code> field into the given object, 181 * using <code>volatile</code> semantics. 182 * 183 * @param obj non-null; object containing the field 184 * @param offset offset to the field within <code>obj</code> 185 * @param newValue the value to store 186 */ putLongVolatile(Object obj, long offset, long newValue)187 public native void putLongVolatile(Object obj, long offset, long newValue); 188 189 /** 190 * Gets an <code>Object</code> field from the given object, 191 * using <code>volatile</code> semantics. 192 * 193 * @param obj non-null; object containing the field 194 * @param offset offset to the field within <code>obj</code> 195 * @return the retrieved value 196 */ getObjectVolatile(Object obj, long offset)197 public native Object getObjectVolatile(Object obj, long offset); 198 199 /** 200 * Stores an <code>Object</code> field into the given object, 201 * using <code>volatile</code> semantics. 202 * 203 * @param obj non-null; object containing the field 204 * @param offset offset to the field within <code>obj</code> 205 * @param newValue the value to store 206 */ putObjectVolatile(Object obj, long offset, Object newValue)207 public native void putObjectVolatile(Object obj, long offset, 208 Object newValue); 209 210 /** 211 * Gets an <code>int</code> field from the given object. 212 * 213 * @param obj non-null; object containing the field 214 * @param offset offset to the field within <code>obj</code> 215 * @return the retrieved value 216 */ getInt(Object obj, long offset)217 public native int getInt(Object obj, long offset); 218 219 /** 220 * Stores an <code>int</code> field into the given object. 221 * 222 * @param obj non-null; object containing the field 223 * @param offset offset to the field within <code>obj</code> 224 * @param newValue the value to store 225 */ putInt(Object obj, long offset, int newValue)226 public native void putInt(Object obj, long offset, int newValue); 227 228 /** 229 * Lazy set an int field. 230 */ putOrderedInt(Object obj, long offset, int newValue)231 public native void putOrderedInt(Object obj, long offset, int newValue); 232 233 /** 234 * Gets a <code>long</code> field from the given object. 235 * 236 * @param obj non-null; object containing the field 237 * @param offset offset to the field within <code>obj</code> 238 * @return the retrieved value 239 */ getLong(Object obj, long offset)240 public native long getLong(Object obj, long offset); 241 242 /** 243 * Stores a <code>long</code> field into the given object. 244 * 245 * @param obj non-null; object containing the field 246 * @param offset offset to the field within <code>obj</code> 247 * @param newValue the value to store 248 */ putLong(Object obj, long offset, long newValue)249 public native void putLong(Object obj, long offset, long newValue); 250 251 /** 252 * Lazy set a long field. 253 */ putOrderedLong(Object obj, long offset, long newValue)254 public native void putOrderedLong(Object obj, long offset, long newValue); 255 256 /** 257 * Gets an <code>Object</code> field from the given object. 258 * 259 * @param obj non-null; object containing the field 260 * @param offset offset to the field within <code>obj</code> 261 * @return the retrieved value 262 */ getObject(Object obj, long offset)263 public native Object getObject(Object obj, long offset); 264 265 /** 266 * Stores an <code>Object</code> field into the given object. 267 * 268 * @param obj non-null; object containing the field 269 * @param offset offset to the field within <code>obj</code> 270 * @param newValue the value to store 271 */ putObject(Object obj, long offset, Object newValue)272 public native void putObject(Object obj, long offset, Object newValue); 273 274 /** 275 * Lazy set an object field. 276 */ putOrderedObject(Object obj, long offset, Object newValue)277 public native void putOrderedObject(Object obj, long offset, 278 Object newValue); 279 280 /** 281 * Parks the calling thread for the specified amount of time, 282 * unless the "permit" for the thread is already available (due to 283 * a previous call to {@link #unpark}. This method may also return 284 * spuriously (that is, without the thread being told to unpark 285 * and without the indicated amount of time elapsing). 286 * 287 * <p>See {@link java.util.concurrent.locks.LockSupport} for more 288 * in-depth information of the behavior of this method.</p> 289 * 290 * @param absolute whether the given time value is absolute 291 * milliseconds-since-the-epoch (<code>true</code>) or relative 292 * nanoseconds-from-now (<code>false</code>) 293 * @param time the (absolute millis or relative nanos) time value 294 */ park(boolean absolute, long time)295 public void park(boolean absolute, long time) { 296 if (absolute) { 297 Thread.currentThread().parkUntil(time); 298 } else { 299 Thread.currentThread().parkFor(time); 300 } 301 } 302 303 /** 304 * Unparks the given object, which must be a {@link Thread}. 305 * 306 * <p>See {@link java.util.concurrent.locks.LockSupport} for more 307 * in-depth information of the behavior of this method.</p> 308 * 309 * @param obj non-null; the object to unpark 310 */ unpark(Object obj)311 public void unpark(Object obj) { 312 if (obj instanceof Thread) { 313 ((Thread) obj).unpark(); 314 } else { 315 throw new IllegalArgumentException("valid for Threads only"); 316 } 317 } 318 319 /** 320 * Allocates an instance of the given class without running the constructor. 321 * The class' <clinit> will be run, if necessary. 322 */ allocateInstance(Class<?> c)323 public native Object allocateInstance(Class<?> c); 324 } 325