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