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