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("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 */ 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 // TODO: make the following not specific to the object model. 85 int offset = 12; 86 if (component == long.class || component == double.class) { 87 offset += 4; // 4 bytes of padding. 88 } 89 return offset; 90 } 91 92 /** 93 * Gets the size of each element of the given array class. 94 * 95 * @param clazz non-null; class in question; must be an array class 96 * @return > 0; the size of each element of the array 97 */ 98 public int arrayIndexScale(Class clazz) { 99 Class<?> component = clazz.getComponentType(); 100 if (component == null) { 101 throw new IllegalArgumentException("Valid for array classes only: " + clazz); 102 } 103 // TODO: make the following not specific to the object model. 104 if (!component.isPrimitive()) { 105 return 4; 106 } else if (component == long.class || component == double.class) { 107 return 8; 108 } else if (component == int.class || component == float.class) { 109 return 4; 110 } else if (component == char.class || component == short.class) { 111 return 2; 112 } else { 113 // component == byte.class || component == boolean.class. 114 return 1; 115 } 116 } 117 118 /** 119 * Performs a compare-and-set operation on an <code>int</code> 120 * field within the given object. 121 * 122 * @param obj non-null; object containing the field 123 * @param offset offset to the field within <code>obj</code> 124 * @param expectedValue expected value of the field 125 * @param newValue new value to store in the field if the contents are 126 * as expected 127 * @return <code>true</code> if the new value was in fact stored, and 128 * <code>false</code> if not 129 */ 130 public native boolean compareAndSwapInt(Object obj, long offset, 131 int expectedValue, int newValue); 132 133 /** 134 * Performs a compare-and-set operation on a <code>long</code> 135 * field within the given object. 136 * 137 * @param obj non-null; object containing the field 138 * @param offset offset to the field within <code>obj</code> 139 * @param expectedValue expected value of the field 140 * @param newValue new value to store in the field if the contents are 141 * as expected 142 * @return <code>true</code> if the new value was in fact stored, and 143 * <code>false</code> if not 144 */ 145 public native boolean compareAndSwapLong(Object obj, long offset, 146 long expectedValue, long newValue); 147 148 /** 149 * Performs a compare-and-set operation on an <code>Object</code> 150 * field (that is, a reference field) within the given object. 151 * 152 * @param obj non-null; object containing the field 153 * @param offset offset to the field within <code>obj</code> 154 * @param expectedValue expected value of the field 155 * @param newValue new value to store in the field if the contents are 156 * as expected 157 * @return <code>true</code> if the new value was in fact stored, and 158 * <code>false</code> if not 159 */ 160 public native boolean compareAndSwapObject(Object obj, long offset, 161 Object expectedValue, Object newValue); 162 163 /** 164 * Gets an <code>int</code> field from the given object, 165 * using <code>volatile</code> semantics. 166 * 167 * @param obj non-null; object containing the field 168 * @param offset offset to the field within <code>obj</code> 169 * @return the retrieved value 170 */ 171 public native int getIntVolatile(Object obj, long offset); 172 173 /** 174 * Stores an <code>int</code> field into 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 * @param newValue the value to store 180 */ 181 public native void putIntVolatile(Object obj, long offset, int newValue); 182 183 /** 184 * Gets a <code>long</code> field from 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 * @return the retrieved value 190 */ 191 public native long getLongVolatile(Object obj, long offset); 192 193 /** 194 * Stores a <code>long</code> field into 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 * @param newValue the value to store 200 */ 201 public native void putLongVolatile(Object obj, long offset, long newValue); 202 203 /** 204 * Gets an <code>Object</code> field from 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 * @return the retrieved value 210 */ 211 public native Object getObjectVolatile(Object obj, long offset); 212 213 /** 214 * Stores an <code>Object</code> field into 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 * @param newValue the value to store 220 */ 221 public native void putObjectVolatile(Object obj, long offset, 222 Object newValue); 223 224 /** 225 * Gets an <code>int</code> field from the given object. 226 * 227 * @param obj non-null; object containing the field 228 * @param offset offset to the field within <code>obj</code> 229 * @return the retrieved value 230 */ 231 public native int getInt(Object obj, long offset); 232 233 /** 234 * Stores an <code>int</code> field into 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 * @param newValue the value to store 239 */ 240 public native void putInt(Object obj, long offset, int newValue); 241 242 /** 243 * Lazy set an int field. 244 */ 245 public native void putOrderedInt(Object obj, long offset, int newValue); 246 247 /** 248 * Gets a <code>long</code> field from the given object. 249 * 250 * @param obj non-null; object containing the field 251 * @param offset offset to the field within <code>obj</code> 252 * @return the retrieved value 253 */ 254 public native long getLong(Object obj, long offset); 255 256 /** 257 * Stores a <code>long</code> field into 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 * @param newValue the value to store 262 */ 263 public native void putLong(Object obj, long offset, long newValue); 264 265 /** 266 * Lazy set a long field. 267 */ 268 public native void putOrderedLong(Object obj, long offset, long newValue); 269 270 /** 271 * Gets an <code>Object</code> field from the given object. 272 * 273 * @param obj non-null; object containing the field 274 * @param offset offset to the field within <code>obj</code> 275 * @return the retrieved value 276 */ 277 public native Object getObject(Object obj, long offset); 278 279 /** 280 * Stores an <code>Object</code> field into the given object. 281 * 282 * @param obj non-null; object containing the field 283 * @param offset offset to the field within <code>obj</code> 284 * @param newValue the value to store 285 */ 286 public native void putObject(Object obj, long offset, Object newValue); 287 288 /** 289 * Lazy set an object field. 290 */ 291 public native void putOrderedObject(Object obj, long offset, 292 Object newValue); 293 294 /** 295 * Parks the calling thread for the specified amount of time, 296 * unless the "permit" for the thread is already available (due to 297 * a previous call to {@link #unpark}. This method may also return 298 * spuriously (that is, without the thread being told to unpark 299 * and without the indicated amount of time elapsing). 300 * 301 * <p>See {@link java.util.concurrent.locks.LockSupport} for more 302 * in-depth information of the behavior of this method.</p> 303 * 304 * @param absolute whether the given time value is absolute 305 * milliseconds-since-the-epoch (<code>true</code>) or relative 306 * nanoseconds-from-now (<code>false</code>) 307 * @param time the (absolute millis or relative nanos) time value 308 */ 309 public void park(boolean absolute, long time) { 310 if (absolute) { 311 Thread.currentThread().parkUntil(time); 312 } else { 313 Thread.currentThread().parkFor(time); 314 } 315 } 316 317 /** 318 * Unparks the given object, which must be a {@link Thread}. 319 * 320 * <p>See {@link java.util.concurrent.locks.LockSupport} for more 321 * in-depth information of the behavior of this method.</p> 322 * 323 * @param obj non-null; the object to unpark 324 */ 325 public void unpark(Object obj) { 326 if (obj instanceof Thread) { 327 ((Thread) obj).unpark(); 328 } else { 329 throw new IllegalArgumentException("valid for Threads only"); 330 } 331 } 332 333 /** 334 * Allocates an instance of the given class without running the constructor. 335 * The class' <clinit> will be run, if necessary. 336 */ 337 public native Object allocateInstance(Class<?> c); 338 } 339