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 */ 38 private Unsafe() {} 39 40 /** 41 * Gets the unique instance of this class. This is only allowed in 42 * very limited situations. 43 */ 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 */ 65 public long objectFieldOffset(Field field) { 66 if (Modifier.isStatic(field.getModifiers())) { 67 throw new IllegalArgumentException( 68 "valid for instance fields only"); 69 } 70 71 return objectFieldOffset0(field); 72 } 73 74 /** 75 * Helper for {@link #objectFieldOffset}, which does all the work, 76 * assuming the parameter is deemed valid. 77 * 78 * @param field non-null; the instance field 79 * @return the offset to the field 80 */ 81 private static native long objectFieldOffset0(Field field); 82 83 /** 84 * Gets the offset from the start of an array object's memory to 85 * the memory used to store its initial (zeroeth) element. 86 * 87 * @param clazz non-null; class in question; must be an array class 88 * @return the offset to the initial element 89 */ 90 public int arrayBaseOffset(Class clazz) { 91 if (! clazz.isArray()) { 92 throw new IllegalArgumentException( 93 "valid for array classes only"); 94 } 95 96 return arrayBaseOffset0(clazz); 97 } 98 99 /** 100 * Helper for {@link #arrayBaseOffset}, which does all the work, 101 * assuming the parameter is deemed valid. 102 * 103 * @return the offset to the field 104 */ 105 private static native int arrayBaseOffset0(Class clazz); 106 107 /** 108 * Gets the size of each element of the given array class. 109 * 110 * @param clazz non-null; class in question; must be an array class 111 * @return > 0; the size of each element of the array 112 */ 113 public int arrayIndexScale(Class clazz) { 114 if (! clazz.isArray()) { 115 throw new IllegalArgumentException( 116 "valid for array classes only"); 117 } 118 119 return arrayIndexScale0(clazz); 120 } 121 122 /** 123 * Helper for {@link #arrayIndexScale}, which does all the work, 124 * assuming the parameter is deemed valid. 125 * 126 * @return the offset to the field 127 */ 128 private static native int arrayIndexScale0(Class clazz); 129 130 /** 131 * Performs a compare-and-set operation on an <code>int</code> 132 * field within the given object. 133 * 134 * @param obj non-null; object containing the field 135 * @param offset offset to the field within <code>obj</code> 136 * @param expectedValue expected value of the field 137 * @param newValue new value to store in the field if the contents are 138 * as expected 139 * @return <code>true</code> if the new value was in fact stored, and 140 * <code>false</code> if not 141 */ 142 public native boolean compareAndSwapInt(Object obj, long offset, 143 int expectedValue, int newValue); 144 145 /** 146 * Performs a compare-and-set operation on a <code>long</code> 147 * field within the given object. 148 * 149 * @param obj non-null; object containing the field 150 * @param offset offset to the field within <code>obj</code> 151 * @param expectedValue expected value of the field 152 * @param newValue new value to store in the field if the contents are 153 * as expected 154 * @return <code>true</code> if the new value was in fact stored, and 155 * <code>false</code> if not 156 */ 157 public native boolean compareAndSwapLong(Object obj, long offset, 158 long expectedValue, long newValue); 159 160 /** 161 * Performs a compare-and-set operation on an <code>Object</code> 162 * field (that is, a reference field) within the given object. 163 * 164 * @param obj non-null; object containing the field 165 * @param offset offset to the field within <code>obj</code> 166 * @param expectedValue expected value of the field 167 * @param newValue new value to store in the field if the contents are 168 * as expected 169 * @return <code>true</code> if the new value was in fact stored, and 170 * <code>false</code> if not 171 */ 172 public native boolean compareAndSwapObject(Object obj, long offset, 173 Object expectedValue, Object newValue); 174 175 /** 176 * Gets an <code>int</code> field from the given object, 177 * using <code>volatile</code> semantics. 178 * 179 * @param obj non-null; object containing the field 180 * @param offset offset to the field within <code>obj</code> 181 * @return the retrieved value 182 */ 183 public native int getIntVolatile(Object obj, long offset); 184 185 /** 186 * Stores an <code>int</code> field into the given object, 187 * using <code>volatile</code> semantics. 188 * 189 * @param obj non-null; object containing the field 190 * @param offset offset to the field within <code>obj</code> 191 * @param newValue the value to store 192 */ 193 public native void putIntVolatile(Object obj, long offset, int newValue); 194 195 /** 196 * Gets a <code>long</code> field from the given object, 197 * using <code>volatile</code> semantics. 198 * 199 * @param obj non-null; object containing the field 200 * @param offset offset to the field within <code>obj</code> 201 * @return the retrieved value 202 */ 203 public native long getLongVolatile(Object obj, long offset); 204 205 /** 206 * Stores a <code>long</code> field into the given object, 207 * using <code>volatile</code> semantics. 208 * 209 * @param obj non-null; object containing the field 210 * @param offset offset to the field within <code>obj</code> 211 * @param newValue the value to store 212 */ 213 public native void putLongVolatile(Object obj, long offset, long newValue); 214 215 /** 216 * Gets an <code>Object</code> field from the given object, 217 * using <code>volatile</code> semantics. 218 * 219 * @param obj non-null; object containing the field 220 * @param offset offset to the field within <code>obj</code> 221 * @return the retrieved value 222 */ 223 public native Object getObjectVolatile(Object obj, long offset); 224 225 /** 226 * Stores an <code>Object</code> field into the given object, 227 * using <code>volatile</code> semantics. 228 * 229 * @param obj non-null; object containing the field 230 * @param offset offset to the field within <code>obj</code> 231 * @param newValue the value to store 232 */ 233 public native void putObjectVolatile(Object obj, long offset, 234 Object newValue); 235 236 /** 237 * Gets an <code>int</code> field from the given object. 238 * 239 * @param obj non-null; object containing the field 240 * @param offset offset to the field within <code>obj</code> 241 * @return the retrieved value 242 */ 243 public native int getInt(Object obj, long offset); 244 245 /** 246 * Stores an <code>int</code> field into the given object. 247 * 248 * @param obj non-null; object containing the field 249 * @param offset offset to the field within <code>obj</code> 250 * @param newValue the value to store 251 */ 252 public native void putInt(Object obj, long offset, int newValue); 253 254 /** 255 * Lazy set an int field. 256 */ 257 public native void putOrderedInt(Object obj, long offset, int newValue); 258 259 /** 260 * Gets a <code>long</code> field from the given object. 261 * 262 * @param obj non-null; object containing the field 263 * @param offset offset to the field within <code>obj</code> 264 * @return the retrieved value 265 */ 266 public native long getLong(Object obj, long offset); 267 268 /** 269 * Stores a <code>long</code> field into the given object. 270 * 271 * @param obj non-null; object containing the field 272 * @param offset offset to the field within <code>obj</code> 273 * @param newValue the value to store 274 */ 275 public native void putLong(Object obj, long offset, long newValue); 276 277 /** 278 * Lazy set a long field. 279 */ 280 public native void putOrderedLong(Object obj, long offset, long newValue); 281 282 /** 283 * Gets an <code>Object</code> field from the given object. 284 * 285 * @param obj non-null; object containing the field 286 * @param offset offset to the field within <code>obj</code> 287 * @return the retrieved value 288 */ 289 public native Object getObject(Object obj, long offset); 290 291 /** 292 * Stores an <code>Object</code> field into the given object. 293 * 294 * @param obj non-null; object containing the field 295 * @param offset offset to the field within <code>obj</code> 296 * @param newValue the value to store 297 */ 298 public native void putObject(Object obj, long offset, Object newValue); 299 300 /** 301 * Lazy set an object field. 302 */ 303 public native void putOrderedObject(Object obj, long offset, 304 Object newValue); 305 306 /** 307 * Parks the calling thread for the specified amount of time, 308 * unless the "permit" for the thread is already available (due to 309 * a previous call to {@link #unpark}. This method may also return 310 * spuriously (that is, without the thread being told to unpark 311 * and without the indicated amount of time elapsing). 312 * 313 * <p>See {@link java.util.concurrent.locks.LockSupport} for more 314 * in-depth information of the behavior of this method.</p> 315 * 316 * @param absolute whether the given time value is absolute 317 * milliseconds-since-the-epoch (<code>true</code>) or relative 318 * nanoseconds-from-now (<code>false</code>) 319 * @param time the (absolute millis or relative nanos) time value 320 */ 321 public void park(boolean absolute, long time) { 322 if (absolute) { 323 Thread.currentThread().parkUntil(time); 324 } else { 325 Thread.currentThread().parkFor(time); 326 } 327 } 328 329 /** 330 * Unparks the given object, which must be a {@link Thread}. 331 * 332 * <p>See {@link java.util.concurrent.locks.LockSupport} for more 333 * in-depth information of the behavior of this method.</p> 334 * 335 * @param obj non-null; the object to unpark 336 */ 337 public void unpark(Object obj) { 338 if (obj instanceof Thread) { 339 ((Thread) obj).unpark(); 340 } else { 341 throw new IllegalArgumentException("valid for Threads only"); 342 } 343 } 344 345 /** 346 * Allocates an instance of the given class without running the constructor. 347 * The class' <clinit> will be run, if necessary. 348 */ 349 public native Object allocateInstance(Class<?> c); 350 } 351