• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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(
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      */
objectFieldOffset0(Field field)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      */
arrayBaseOffset(Class clazz)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      */
arrayBaseOffset0(Class clazz)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      */
arrayIndexScale(Class clazz)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      */
arrayIndexScale0(Class clazz)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      */
compareAndSwapInt(Object obj, long offset, int expectedValue, int newValue)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      */
compareAndSwapLong(Object obj, long offset, long expectedValue, long newValue)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      */
compareAndSwapObject(Object obj, long offset, Object expectedValue, Object newValue)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      */
getIntVolatile(Object obj, long offset)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      */
putIntVolatile(Object obj, long offset, int newValue)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      */
getLongVolatile(Object obj, long offset)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      */
putLongVolatile(Object obj, long offset, long newValue)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      */
getObjectVolatile(Object obj, long offset)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      */
putObjectVolatile(Object obj, long offset, Object newValue)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      */
getInt(Object obj, long offset)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      */
putInt(Object obj, long offset, int newValue)252     public native void putInt(Object obj, long offset, int newValue);
253 
254     /**
255      * Lazy set an int field.
256      */
putOrderedInt(Object obj, long offset, int newValue)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      */
getLong(Object obj, long offset)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      */
putLong(Object obj, long offset, long newValue)275     public native void putLong(Object obj, long offset, long newValue);
276 
277     /**
278      * Lazy set a long field.
279      */
putOrderedLong(Object obj, long offset, long newValue)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      */
getObject(Object obj, long offset)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      */
putObject(Object obj, long offset, Object newValue)298     public native void putObject(Object obj, long offset, Object newValue);
299 
300     /**
301      * Lazy set an object field.
302      */
putOrderedObject(Object obj, long offset, Object newValue)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      */
park(boolean absolute, long time)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      */
unpark(Object obj)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      */
allocateInstance(Class<?> c)349     public native Object allocateInstance(Class<?> c);
350 }
351