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