• 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("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         // TODO: make the following not specific to the object model.
85         int offset = 12;
86         if (component == long.class || component == double.class) {
87             offset += 4;  // 4 bytes of padding.
88         }
89         return offset;
90     }
91 
92     /**
93      * Gets the size of each element of the given array class.
94      *
95      * @param clazz non-null; class in question; must be an array class
96      * @return &gt; 0; the size of each element of the array
97      */
arrayIndexScale(Class clazz)98     public int arrayIndexScale(Class clazz) {
99       Class<?> component = clazz.getComponentType();
100       if (component == null) {
101           throw new IllegalArgumentException("Valid for array classes only: " + clazz);
102       }
103       // TODO: make the following not specific to the object model.
104       if (!component.isPrimitive()) {
105           return 4;
106       } else  if (component == long.class || component == double.class) {
107           return 8;
108       } else if (component == int.class || component == float.class) {
109           return 4;
110       } else if (component == char.class || component == short.class) {
111           return 2;
112       } else {
113           // component == byte.class || component == boolean.class.
114           return 1;
115       }
116     }
117 
118     /**
119      * Performs a compare-and-set operation on an <code>int</code>
120      * field within the given object.
121      *
122      * @param obj non-null; object containing the field
123      * @param offset offset to the field within <code>obj</code>
124      * @param expectedValue expected value of the field
125      * @param newValue new value to store in the field if the contents are
126      * as expected
127      * @return <code>true</code> if the new value was in fact stored, and
128      * <code>false</code> if not
129      */
compareAndSwapInt(Object obj, long offset, int expectedValue, int newValue)130     public native boolean compareAndSwapInt(Object obj, long offset,
131             int expectedValue, int newValue);
132 
133     /**
134      * Performs a compare-and-set operation on a <code>long</code>
135      * field within the given object.
136      *
137      * @param obj non-null; object containing the field
138      * @param offset offset to the field within <code>obj</code>
139      * @param expectedValue expected value of the field
140      * @param newValue new value to store in the field if the contents are
141      * as expected
142      * @return <code>true</code> if the new value was in fact stored, and
143      * <code>false</code> if not
144      */
compareAndSwapLong(Object obj, long offset, long expectedValue, long newValue)145     public native boolean compareAndSwapLong(Object obj, long offset,
146             long expectedValue, long newValue);
147 
148     /**
149      * Performs a compare-and-set operation on an <code>Object</code>
150      * field (that is, a reference field) within the given object.
151      *
152      * @param obj non-null; object containing the field
153      * @param offset offset to the field within <code>obj</code>
154      * @param expectedValue expected value of the field
155      * @param newValue new value to store in the field if the contents are
156      * as expected
157      * @return <code>true</code> if the new value was in fact stored, and
158      * <code>false</code> if not
159      */
compareAndSwapObject(Object obj, long offset, Object expectedValue, Object newValue)160     public native boolean compareAndSwapObject(Object obj, long offset,
161             Object expectedValue, Object newValue);
162 
163     /**
164      * Gets an <code>int</code> field from the given object,
165      * using <code>volatile</code> semantics.
166      *
167      * @param obj non-null; object containing the field
168      * @param offset offset to the field within <code>obj</code>
169      * @return the retrieved value
170      */
getIntVolatile(Object obj, long offset)171     public native int getIntVolatile(Object obj, long offset);
172 
173     /**
174      * Stores an <code>int</code> field into 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      * @param newValue the value to store
180      */
putIntVolatile(Object obj, long offset, int newValue)181     public native void putIntVolatile(Object obj, long offset, int newValue);
182 
183     /**
184      * Gets a <code>long</code> field from 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      * @return the retrieved value
190      */
getLongVolatile(Object obj, long offset)191     public native long getLongVolatile(Object obj, long offset);
192 
193     /**
194      * Stores a <code>long</code> field into 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      * @param newValue the value to store
200      */
putLongVolatile(Object obj, long offset, long newValue)201     public native void putLongVolatile(Object obj, long offset, long newValue);
202 
203     /**
204      * Gets an <code>Object</code> field from 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      * @return the retrieved value
210      */
getObjectVolatile(Object obj, long offset)211     public native Object getObjectVolatile(Object obj, long offset);
212 
213     /**
214      * Stores an <code>Object</code> field into 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      * @param newValue the value to store
220      */
putObjectVolatile(Object obj, long offset, Object newValue)221     public native void putObjectVolatile(Object obj, long offset,
222             Object newValue);
223 
224     /**
225      * Gets an <code>int</code> field from the given object.
226      *
227      * @param obj non-null; object containing the field
228      * @param offset offset to the field within <code>obj</code>
229      * @return the retrieved value
230      */
getInt(Object obj, long offset)231     public native int getInt(Object obj, long offset);
232 
233     /**
234      * Stores an <code>int</code> field into 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      * @param newValue the value to store
239      */
putInt(Object obj, long offset, int newValue)240     public native void putInt(Object obj, long offset, int newValue);
241 
242     /**
243      * Lazy set an int field.
244      */
putOrderedInt(Object obj, long offset, int newValue)245     public native void putOrderedInt(Object obj, long offset, int newValue);
246 
247     /**
248      * Gets a <code>long</code> field from the given object.
249      *
250      * @param obj non-null; object containing the field
251      * @param offset offset to the field within <code>obj</code>
252      * @return the retrieved value
253      */
getLong(Object obj, long offset)254     public native long getLong(Object obj, long offset);
255 
256     /**
257      * Stores a <code>long</code> field into 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      * @param newValue the value to store
262      */
putLong(Object obj, long offset, long newValue)263     public native void putLong(Object obj, long offset, long newValue);
264 
265     /**
266      * Lazy set a long field.
267      */
putOrderedLong(Object obj, long offset, long newValue)268     public native void putOrderedLong(Object obj, long offset, long newValue);
269 
270     /**
271      * Gets an <code>Object</code> field from the given object.
272      *
273      * @param obj non-null; object containing the field
274      * @param offset offset to the field within <code>obj</code>
275      * @return the retrieved value
276      */
getObject(Object obj, long offset)277     public native Object getObject(Object obj, long offset);
278 
279     /**
280      * Stores an <code>Object</code> field into the given object.
281      *
282      * @param obj non-null; object containing the field
283      * @param offset offset to the field within <code>obj</code>
284      * @param newValue the value to store
285      */
putObject(Object obj, long offset, Object newValue)286     public native void putObject(Object obj, long offset, Object newValue);
287 
288     /**
289      * Lazy set an object field.
290      */
putOrderedObject(Object obj, long offset, Object newValue)291     public native void putOrderedObject(Object obj, long offset,
292             Object newValue);
293 
294     /**
295      * Parks the calling thread for the specified amount of time,
296      * unless the "permit" for the thread is already available (due to
297      * a previous call to {@link #unpark}. This method may also return
298      * spuriously (that is, without the thread being told to unpark
299      * and without the indicated amount of time elapsing).
300      *
301      * <p>See {@link java.util.concurrent.locks.LockSupport} for more
302      * in-depth information of the behavior of this method.</p>
303      *
304      * @param absolute whether the given time value is absolute
305      * milliseconds-since-the-epoch (<code>true</code>) or relative
306      * nanoseconds-from-now (<code>false</code>)
307      * @param time the (absolute millis or relative nanos) time value
308      */
park(boolean absolute, long time)309     public void park(boolean absolute, long time) {
310         if (absolute) {
311             Thread.currentThread().parkUntil(time);
312         } else {
313             Thread.currentThread().parkFor(time);
314         }
315     }
316 
317     /**
318      * Unparks the given object, which must be a {@link Thread}.
319      *
320      * <p>See {@link java.util.concurrent.locks.LockSupport} for more
321      * in-depth information of the behavior of this method.</p>
322      *
323      * @param obj non-null; the object to unpark
324      */
unpark(Object obj)325     public void unpark(Object obj) {
326         if (obj instanceof Thread) {
327             ((Thread) obj).unpark();
328         } else {
329             throw new IllegalArgumentException("valid for Threads only");
330         }
331     }
332 
333     /**
334      * Allocates an instance of the given class without running the constructor.
335      * The class' <clinit> will be run, if necessary.
336      */
allocateInstance(Class<?> c)337     public native Object allocateInstance(Class<?> c);
338 }
339