• 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     /** non-null; unique instance of this class */
31     private static final Unsafe THE_ONE = new Unsafe();
32 
33     /**
34      * This class is only privately instantiable.
35      */
Unsafe()36     private Unsafe() {}
37 
38     /**
39      * Gets the unique instance of this class. This is only allowed in
40      * very limited situations.
41      */
getUnsafe()42     public static Unsafe getUnsafe() {
43         /*
44          * Only code on the bootclasspath is allowed to get at the
45          * Unsafe instance.
46          */
47         ClassLoader calling = VMStack.getCallingClassLoader();
48         if ((calling != null) && (calling != Unsafe.class.getClassLoader())) {
49             throw new SecurityException("Unsafe access denied");
50         }
51 
52         return THE_ONE;
53     }
54 
55     /**
56      * Gets the raw byte offset from the start of an object's memory to
57      * the memory used to store the indicated instance field.
58      *
59      * @param field non-null; the field in question, which must be an
60      * instance field
61      * @return the offset to the field
62      */
objectFieldOffset(Field field)63     public long objectFieldOffset(Field field) {
64         if (Modifier.isStatic(field.getModifiers())) {
65             throw new IllegalArgumentException(
66                     "valid for instance fields only");
67         }
68 
69         return objectFieldOffset0(field);
70     }
71 
72     /**
73      * Helper for {@link #objectFieldOffset}, which does all the work,
74      * assuming the parameter is deemed valid.
75      *
76      * @param field non-null; the instance field
77      * @return the offset to the field
78      */
objectFieldOffset0(Field field)79     private static native long objectFieldOffset0(Field field);
80 
81     /**
82      * Gets the offset from the start of an array object's memory to
83      * the memory used to store its initial (zeroeth) element.
84      *
85      * @param clazz non-null; class in question; must be an array class
86      * @return the offset to the initial element
87      */
arrayBaseOffset(Class clazz)88     public int arrayBaseOffset(Class clazz) {
89         if (! clazz.isArray()) {
90             throw new IllegalArgumentException(
91                     "valid for array classes only");
92         }
93 
94         return arrayBaseOffset0(clazz);
95     }
96 
97     /**
98      * Helper for {@link #arrayBaseOffset}, which does all the work,
99      * assuming the parameter is deemed valid.
100      *
101      * @return the offset to the field
102      */
arrayBaseOffset0(Class clazz)103     private static native int arrayBaseOffset0(Class clazz);
104 
105     /**
106      * Gets the size of each element of the given array class.
107      *
108      * @param clazz non-null; class in question; must be an array class
109      * @return > 0; the size of each element of the array
110      */
arrayIndexScale(Class clazz)111     public int arrayIndexScale(Class clazz) {
112         if (! clazz.isArray()) {
113             throw new IllegalArgumentException(
114                     "valid for array classes only");
115         }
116 
117         return arrayIndexScale0(clazz);
118     }
119 
120     /**
121      * Helper for {@link #arrayIndexScale}, which does all the work,
122      * assuming the parameter is deemed valid.
123      *
124      * @return the offset to the field
125      */
arrayIndexScale0(Class clazz)126     private static native int arrayIndexScale0(Class clazz);
127 
128     /**
129      * Performs a compare-and-set operation on an <code>int</code>
130      * field within the given object.
131      *
132      * @param obj non-null; object containing the field
133      * @param offset offset to the field within <code>obj</code>
134      * @param expectedValue expected value of the field
135      * @param newValue new value to store in the field if the contents are
136      * as expected
137      * @return <code>true</code> if the new value was in fact stored, and
138      * <code>false</code> if not
139      */
compareAndSwapInt(Object obj, long offset, int expectedValue, int newValue)140     public native boolean compareAndSwapInt(Object obj, long offset,
141             int expectedValue, int newValue);
142 
143     /**
144      * Performs a compare-and-set operation on a <code>long</code>
145      * field within the given object.
146      *
147      * @param obj non-null; object containing the field
148      * @param offset offset to the field within <code>obj</code>
149      * @param expectedValue expected value of the field
150      * @param newValue new value to store in the field if the contents are
151      * as expected
152      * @return <code>true</code> if the new value was in fact stored, and
153      * <code>false</code> if not
154      */
compareAndSwapLong(Object obj, long offset, long expectedValue, long newValue)155     public native boolean compareAndSwapLong(Object obj, long offset,
156             long expectedValue, long newValue);
157 
158     /**
159      * Performs a compare-and-set operation on an <code>Object</code>
160      * field (that is, a reference field) within the given object.
161      *
162      * @param obj non-null; object containing the field
163      * @param offset offset to the field within <code>obj</code>
164      * @param expectedValue expected value of the field
165      * @param newValue new value to store in the field if the contents are
166      * as expected
167      * @return <code>true</code> if the new value was in fact stored, and
168      * <code>false</code> if not
169      */
compareAndSwapObject(Object obj, long offset, Object expectedValue, Object newValue)170     public native boolean compareAndSwapObject(Object obj, long offset,
171             Object expectedValue, Object newValue);
172 
173     /**
174      * Gets an <code>int</code> field from the given object,
175      * using <code>volatile</code> semantics.
176      *
177      * @param obj non-null; object containing the field
178      * @param offset offset to the field within <code>obj</code>
179      * @return the retrieved value
180      */
getIntVolatile(Object obj, long offset)181     public native int getIntVolatile(Object obj, long offset);
182 
183     /**
184      * Stores an <code>int</code> field into the given object,
185      * using <code>volatile</code> semantics.
186      *
187      * @param obj non-null; object containing the field
188      * @param offset offset to the field within <code>obj</code>
189      * @param newValue the value to store
190      */
putIntVolatile(Object obj, long offset, int newValue)191     public native void putIntVolatile(Object obj, long offset, int newValue);
192 
193     /**
194      * Gets a <code>long</code> field from the given object,
195      * using <code>volatile</code> semantics.
196      *
197      * @param obj non-null; object containing the field
198      * @param offset offset to the field within <code>obj</code>
199      * @return the retrieved value
200      */
getLongVolatile(Object obj, long offset)201     public native long getLongVolatile(Object obj, long offset);
202 
203     /**
204      * Stores a <code>long</code> field into the given object,
205      * using <code>volatile</code> semantics.
206      *
207      * @param obj non-null; object containing the field
208      * @param offset offset to the field within <code>obj</code>
209      * @param newValue the value to store
210      */
putLongVolatile(Object obj, long offset, long newValue)211     public native void putLongVolatile(Object obj, long offset, long newValue);
212 
213     /**
214      * Gets an <code>Object</code> field from the given object,
215      * using <code>volatile</code> semantics.
216      *
217      * @param obj non-null; object containing the field
218      * @param offset offset to the field within <code>obj</code>
219      * @return the retrieved value
220      */
getObjectVolatile(Object obj, long offset)221     public native Object getObjectVolatile(Object obj, long offset);
222 
223     /**
224      * Stores an <code>Object</code> field into the given object,
225      * using <code>volatile</code> semantics.
226      *
227      * @param obj non-null; object containing the field
228      * @param offset offset to the field within <code>obj</code>
229      * @param newValue the value to store
230      */
putObjectVolatile(Object obj, long offset, Object newValue)231     public native void putObjectVolatile(Object obj, long offset,
232             Object newValue);
233 
234     /**
235      * Gets an <code>int</code> field from the given object.
236      *
237      * @param obj non-null; object containing the field
238      * @param offset offset to the field within <code>obj</code>
239      * @return the retrieved value
240      */
getInt(Object obj, long offset)241     public native int getInt(Object obj, long offset);
242 
243     /**
244      * Stores an <code>int</code> field into the given object.
245      *
246      * @param obj non-null; object containing the field
247      * @param offset offset to the field within <code>obj</code>
248      * @param newValue the value to store
249      */
putInt(Object obj, long offset, int newValue)250     public native void putInt(Object obj, long offset, int newValue);
251 
252     /**
253      * Lazy set an int field.
254      */
putOrderedInt(Object obj, long offset, int newValue)255     public native void putOrderedInt(Object obj, long offset, int newValue);
256 
257     /**
258      * Gets a <code>long</code> field from the given object.
259      *
260      * @param obj non-null; object containing the field
261      * @param offset offset to the field within <code>obj</code>
262      * @return the retrieved value
263      */
getLong(Object obj, long offset)264     public native long getLong(Object obj, long offset);
265 
266     /**
267      * Stores a <code>long</code> field into the given object.
268      *
269      * @param obj non-null; object containing the field
270      * @param offset offset to the field within <code>obj</code>
271      * @param newValue the value to store
272      */
putLong(Object obj, long offset, long newValue)273     public native void putLong(Object obj, long offset, long newValue);
274 
275     /**
276      * Lazy set a long field.
277      */
putOrderedLong(Object obj, long offset, long newValue)278     public native void putOrderedLong(Object obj, long offset, long newValue);
279 
280     /**
281      * Gets an <code>Object</code> field from the given object.
282      *
283      * @param obj non-null; object containing the field
284      * @param offset offset to the field within <code>obj</code>
285      * @return the retrieved value
286      */
getObject(Object obj, long offset)287     public native Object getObject(Object obj, long offset);
288 
289     /**
290      * Stores an <code>Object</code> field into the given object.
291      *
292      * @param obj non-null; object containing the field
293      * @param offset offset to the field within <code>obj</code>
294      * @param newValue the value to store
295      */
putObject(Object obj, long offset, Object newValue)296     public native void putObject(Object obj, long offset, Object newValue);
297 
298     /**
299      * Lazy set an object field.
300      */
putOrderedObject(Object obj, long offset, Object newValue)301     public native void putOrderedObject(Object obj, long offset,
302             Object newValue);
303 
304     /**
305      * Parks the calling thread for the specified amount of time,
306      * unless the "permit" for the thread is already available (due to
307      * a previous call to {@link #unpark}. This method may also return
308      * spuriously (that is, without the thread being told to unpark
309      * and without the indicated amount of time elapsing).
310      *
311      * <p>See {@link java.util.concurrent.locks.LockSupport} for more
312      * in-depth information of the behavior of this method.</p>
313      *
314      * @param absolute whether the given time value is absolute
315      * milliseconds-since-the-epoch (<code>true</code>) or relative
316      * nanoseconds-from-now (<code>false</code>)
317      * @param time the (absolute millis or relative nanos) time value
318      */
park(boolean absolute, long time)319     public void park(boolean absolute, long time) {
320         if (absolute) {
321             Thread.currentThread().parkUntil(time);
322         } else {
323             Thread.currentThread().parkFor(time);
324         }
325     }
326 
327     /**
328      * Unparks the given object, which must be a {@link Thread}.
329      *
330      * <p>See {@link java.util.concurrent.locks.LockSupport} for more
331      * in-depth information of the behavior of this method.</p>
332      *
333      * @param obj non-null; the object to unpark
334      */
unpark(Object obj)335     public void unpark(Object obj) {
336         if (obj instanceof Thread) {
337             ((Thread) obj).unpark();
338         } else {
339             throw new IllegalArgumentException("valid for Threads only");
340         }
341     }
342 }
343