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