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 import java.lang.reflect.Field;
21 import 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  */
29 public 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      */
Unsafe()38     private Unsafe() {}
39 
40     /**
41      * Gets the unique instance of this class. This is only allowed in
42      * very limited situations.
43      */
getUnsafe()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      */
objectFieldOffset(Field field)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      */
arrayBaseOffset(Class clazz)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      */
arrayIndexScale(Class clazz)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 
getArrayBaseOffsetForComponentType(Class component_class)101     private static native int getArrayBaseOffsetForComponentType(Class component_class);
getArrayIndexScaleForComponentType(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      */
compareAndSwapInt(Object obj, long offset, int expectedValue, int newValue)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      */
compareAndSwapLong(Object obj, long offset, long expectedValue, long newValue)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      */
compareAndSwapObject(Object obj, long offset, Object expectedValue, Object newValue)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      */
getIntVolatile(Object obj, long offset)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      */
putIntVolatile(Object obj, long offset, int newValue)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      */
getLongVolatile(Object obj, long offset)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      */
putLongVolatile(Object obj, long offset, long newValue)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      */
getObjectVolatile(Object obj, long offset)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      */
putObjectVolatile(Object obj, long offset, Object newValue)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      */
getInt(Object obj, long offset)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      */
putInt(Object obj, long offset, int newValue)226     public native void putInt(Object obj, long offset, int newValue);
227 
228     /**
229      * Lazy set an int field.
230      */
putOrderedInt(Object obj, long offset, int newValue)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      */
getLong(Object obj, long offset)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      */
putLong(Object obj, long offset, long newValue)249     public native void putLong(Object obj, long offset, long newValue);
250 
251     /**
252      * Lazy set a long field.
253      */
putOrderedLong(Object obj, long offset, long newValue)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      */
getObject(Object obj, long offset)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      */
putObject(Object obj, long offset, Object newValue)272     public native void putObject(Object obj, long offset, Object newValue);
273 
274     /**
275      * Lazy set an object field.
276      */
putOrderedObject(Object obj, long offset, Object newValue)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      */
park(boolean absolute, long time)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      */
unpark(Object obj)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      */
allocateInstance(Class<?> c)323     public native Object allocateInstance(Class<?> c);
324 }
325