blob: 6f5f5eee1b0c25cb30488b550e5e9f9b9ea6b990 [file] [log] [blame]
Brian Carlstrom2cf03dc2013-05-22 11:05:31 -07001/*
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;
20import java.lang.reflect.Field;
21import 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 */
29public 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 }
Hiroshi Yamauchi7ce6ae52014-02-11 11:46:18 -080084 return getArrayBaseOffsetForComponentType(component);
Brian Carlstrom2cf03dc2013-05-22 11:05:31 -070085 }
86
87 /**
88 * Gets the size of each element of the given array class.
89 *
90 * @param clazz non-null; class in question; must be an array class
91 * @return &gt; 0; the size of each element of the array
92 */
93 public int arrayIndexScale(Class clazz) {
94 Class<?> component = clazz.getComponentType();
95 if (component == null) {
96 throw new IllegalArgumentException("Valid for array classes only: " + clazz);
97 }
Hiroshi Yamauchi7ce6ae52014-02-11 11:46:18 -080098 return getArrayIndexScaleForComponentType(component);
Brian Carlstrom2cf03dc2013-05-22 11:05:31 -070099 }
100
Hiroshi Yamauchi7ce6ae52014-02-11 11:46:18 -0800101 private static native int getArrayBaseOffsetForComponentType(Class component_class);
102 private static native int getArrayIndexScaleForComponentType(Class component_class);
103
Brian Carlstrom2cf03dc2013-05-22 11:05:31 -0700104 /**
105 * Performs a compare-and-set operation on an <code>int</code>
106 * field within the given object.
107 *
108 * @param obj non-null; object containing the field
109 * @param offset offset to the field within <code>obj</code>
110 * @param expectedValue expected value of the field
111 * @param newValue new value to store in the field if the contents are
112 * as expected
113 * @return <code>true</code> if the new value was in fact stored, and
114 * <code>false</code> if not
115 */
116 public native boolean compareAndSwapInt(Object obj, long offset,
117 int expectedValue, int newValue);
118
119 /**
120 * Performs a compare-and-set operation on a <code>long</code>
121 * field within the given object.
122 *
123 * @param obj non-null; object containing the field
124 * @param offset offset to the field within <code>obj</code>
125 * @param expectedValue expected value of the field
126 * @param newValue new value to store in the field if the contents are
127 * as expected
128 * @return <code>true</code> if the new value was in fact stored, and
129 * <code>false</code> if not
130 */
131 public native boolean compareAndSwapLong(Object obj, long offset,
132 long expectedValue, long newValue);
133
134 /**
135 * Performs a compare-and-set operation on an <code>Object</code>
136 * field (that is, a reference field) within the given object.
137 *
138 * @param obj non-null; object containing the field
139 * @param offset offset to the field within <code>obj</code>
140 * @param expectedValue expected value of the field
141 * @param newValue new value to store in the field if the contents are
142 * as expected
143 * @return <code>true</code> if the new value was in fact stored, and
144 * <code>false</code> if not
145 */
146 public native boolean compareAndSwapObject(Object obj, long offset,
147 Object expectedValue, Object newValue);
148
149 /**
150 * Gets an <code>int</code> field from the given object,
151 * using <code>volatile</code> semantics.
152 *
153 * @param obj non-null; object containing the field
154 * @param offset offset to the field within <code>obj</code>
155 * @return the retrieved value
156 */
157 public native int getIntVolatile(Object obj, long offset);
158
159 /**
160 * Stores an <code>int</code> field into the given object,
161 * using <code>volatile</code> semantics.
162 *
163 * @param obj non-null; object containing the field
164 * @param offset offset to the field within <code>obj</code>
165 * @param newValue the value to store
166 */
167 public native void putIntVolatile(Object obj, long offset, int newValue);
168
169 /**
170 * Gets a <code>long</code> field from the given object,
171 * using <code>volatile</code> semantics.
172 *
173 * @param obj non-null; object containing the field
174 * @param offset offset to the field within <code>obj</code>
175 * @return the retrieved value
176 */
177 public native long getLongVolatile(Object obj, long offset);
178
179 /**
180 * Stores a <code>long</code> field into the given object,
181 * using <code>volatile</code> semantics.
182 *
183 * @param obj non-null; object containing the field
184 * @param offset offset to the field within <code>obj</code>
185 * @param newValue the value to store
186 */
187 public native void putLongVolatile(Object obj, long offset, long newValue);
188
189 /**
190 * Gets an <code>Object</code> field from the given object,
191 * using <code>volatile</code> semantics.
192 *
193 * @param obj non-null; object containing the field
194 * @param offset offset to the field within <code>obj</code>
195 * @return the retrieved value
196 */
197 public native Object getObjectVolatile(Object obj, long offset);
198
199 /**
200 * Stores an <code>Object</code> field into the given object,
201 * using <code>volatile</code> semantics.
202 *
203 * @param obj non-null; object containing the field
204 * @param offset offset to the field within <code>obj</code>
205 * @param newValue the value to store
206 */
207 public native void putObjectVolatile(Object obj, long offset,
208 Object newValue);
209
210 /**
211 * Gets an <code>int</code> field from the given object.
212 *
213 * @param obj non-null; object containing the field
214 * @param offset offset to the field within <code>obj</code>
215 * @return the retrieved value
216 */
217 public native int getInt(Object obj, long offset);
218
219 /**
220 * Stores an <code>int</code> field into the given object.
221 *
222 * @param obj non-null; object containing the field
223 * @param offset offset to the field within <code>obj</code>
224 * @param newValue the value to store
225 */
226 public native void putInt(Object obj, long offset, int newValue);
227
228 /**
229 * Lazy set an int field.
230 */
231 public native void putOrderedInt(Object obj, long offset, int newValue);
232
233 /**
234 * Gets a <code>long</code> field from 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 * @return the retrieved value
239 */
240 public native long getLong(Object obj, long offset);
241
242 /**
243 * Stores a <code>long</code> field into the given object.
244 *
245 * @param obj non-null; object containing the field
246 * @param offset offset to the field within <code>obj</code>
247 * @param newValue the value to store
248 */
249 public native void putLong(Object obj, long offset, long newValue);
250
251 /**
252 * Lazy set a long field.
253 */
254 public native void putOrderedLong(Object obj, long offset, long newValue);
255
256 /**
257 * Gets an <code>Object</code> field from 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 * @return the retrieved value
262 */
263 public native Object getObject(Object obj, long offset);
264
265 /**
266 * Stores an <code>Object</code> field into the given object.
267 *
268 * @param obj non-null; object containing the field
269 * @param offset offset to the field within <code>obj</code>
270 * @param newValue the value to store
271 */
272 public native void putObject(Object obj, long offset, Object newValue);
273
274 /**
275 * Lazy set an object field.
276 */
277 public native void putOrderedObject(Object obj, long offset,
278 Object newValue);
279
280 /**
281 * Parks the calling thread for the specified amount of time,
282 * unless the "permit" for the thread is already available (due to
283 * a previous call to {@link #unpark}. This method may also return
284 * spuriously (that is, without the thread being told to unpark
285 * and without the indicated amount of time elapsing).
286 *
287 * <p>See {@link java.util.concurrent.locks.LockSupport} for more
288 * in-depth information of the behavior of this method.</p>
289 *
290 * @param absolute whether the given time value is absolute
291 * milliseconds-since-the-epoch (<code>true</code>) or relative
292 * nanoseconds-from-now (<code>false</code>)
293 * @param time the (absolute millis or relative nanos) time value
294 */
295 public void park(boolean absolute, long time) {
296 if (absolute) {
297 Thread.currentThread().parkUntil(time);
298 } else {
299 Thread.currentThread().parkFor(time);
300 }
301 }
302
303 /**
304 * Unparks the given object, which must be a {@link Thread}.
305 *
306 * <p>See {@link java.util.concurrent.locks.LockSupport} for more
307 * in-depth information of the behavior of this method.</p>
308 *
309 * @param obj non-null; the object to unpark
310 */
311 public void unpark(Object obj) {
312 if (obj instanceof Thread) {
313 ((Thread) obj).unpark();
314 } else {
315 throw new IllegalArgumentException("valid for Threads only");
316 }
317 }
318
319 /**
320 * Allocates an instance of the given class without running the constructor.
321 * The class' <clinit> will be run, if necessary.
322 */
323 public native Object allocateInstance(Class<?> c);
324}