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