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("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        return getArrayBaseOffsetForComponentType(component);
85    }
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      }
98      return getArrayIndexScaleForComponentType(component);
99    }
100
101    private static native int getArrayBaseOffsetForComponentType(Class component_class);
102    private static native int getArrayIndexScaleForComponentType(Class component_class);
103
104    /**
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}
325