• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * This code is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License version 2 only, as
7  * published by the Free Software Foundation.  Oracle designates this
8  * particular file as subject to the "Classpath" exception as provided
9  * by Oracle in the LICENSE file that accompanied this code.
10  *
11  * This code is distributed in the hope that it will be useful, but WITHOUT
12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14  * version 2 for more details (a copy is included in the LICENSE file that
15  * accompanied this code).
16  *
17  * You should have received a copy of the GNU General Public License version
18  * 2 along with this work; if not, write to the Free Software Foundation,
19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20  *
21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22  * or visit www.oracle.com if you need additional information or have any
23  * questions.
24  */
25 
26 package sun.misc;
27 
28 import dalvik.system.VMStack;
29 import java.lang.reflect.Field;
30 import java.lang.reflect.Modifier;
31 
32 /**
33  * A collection of methods for performing low-level, unsafe operations.
34  * Although the class and all methods are public, use of this class is
35  * limited because only trusted code can obtain instances of it.
36  *
37  * @author John R. Rose
38  * @see #getUnsafe
39  */
40 public final class Unsafe {
41     /** Traditional dalvik name. */
42     private static final Unsafe THE_ONE = new Unsafe();
43 
44     private static final Unsafe theUnsafe = THE_ONE;
45     public static final int INVALID_FIELD_OFFSET   = -1;
46 
47     /**
48      * This class is only privately instantiable.
49      */
Unsafe()50     private Unsafe() {}
51 
52     /**
53      * Gets the unique instance of this class. This is only allowed in
54      * very limited situations.
55      */
getUnsafe()56     public static Unsafe getUnsafe() {
57         /*
58          * Only code on the bootclasspath is allowed to get at the
59          * Unsafe instance.
60          */
61         ClassLoader calling = VMStack.getCallingClassLoader();
62         if ((calling != null) && (calling != Unsafe.class.getClassLoader())) {
63             throw new SecurityException("Unsafe access denied");
64         }
65 
66         return THE_ONE;
67     }
68 
69     /**
70      * Gets the raw byte offset from the start of an object's memory to
71      * the memory used to store the indicated instance field.
72      *
73      * @param field non-null; the field in question, which must be an
74      * instance field
75      * @return the offset to the field
76      */
objectFieldOffset(Field field)77     public long objectFieldOffset(Field field) {
78         if (Modifier.isStatic(field.getModifiers())) {
79             throw new IllegalArgumentException("valid for instance fields only");
80         }
81         return field.getOffset();
82     }
83 
84     /**
85      * Gets the offset from the start of an array object's memory to
86      * the memory used to store its initial (zeroeth) element.
87      *
88      * @param clazz non-null; class in question; must be an array class
89      * @return the offset to the initial element
90      */
arrayBaseOffset(Class clazz)91     public int arrayBaseOffset(Class clazz) {
92         Class<?> component = clazz.getComponentType();
93         if (component == null) {
94             throw new IllegalArgumentException("Valid for array classes only: " + clazz);
95         }
96         return getArrayBaseOffsetForComponentType(component);
97     }
98 
99     /**
100      * Gets the size of each element of the given array class.
101      *
102      * @param clazz non-null; class in question; must be an array class
103      * @return &gt; 0; the size of each element of the array
104      */
arrayIndexScale(Class clazz)105     public int arrayIndexScale(Class clazz) {
106       Class<?> component = clazz.getComponentType();
107       if (component == null) {
108           throw new IllegalArgumentException("Valid for array classes only: " + clazz);
109       }
110       return getArrayIndexScaleForComponentType(component);
111     }
112 
getArrayBaseOffsetForComponentType(Class component_class)113     private static native int getArrayBaseOffsetForComponentType(Class component_class);
getArrayIndexScaleForComponentType(Class component_class)114     private static native int getArrayIndexScaleForComponentType(Class component_class);
115 
116     /**
117      * Performs a compare-and-set operation on an <code>int</code>
118      * field within the given object.
119      *
120      * @param obj non-null; object containing the field
121      * @param offset offset to the field within <code>obj</code>
122      * @param expectedValue expected value of the field
123      * @param newValue new value to store in the field if the contents are
124      * as expected
125      * @return <code>true</code> if the new value was in fact stored, and
126      * <code>false</code> if not
127      */
compareAndSwapInt(Object obj, long offset, int expectedValue, int newValue)128     public native boolean compareAndSwapInt(Object obj, long offset,
129             int expectedValue, int newValue);
130 
131     /**
132      * Performs a compare-and-set operation on a <code>long</code>
133      * field within the given object.
134      *
135      * @param obj non-null; object containing the field
136      * @param offset offset to the field within <code>obj</code>
137      * @param expectedValue expected value of the field
138      * @param newValue new value to store in the field if the contents are
139      * as expected
140      * @return <code>true</code> if the new value was in fact stored, and
141      * <code>false</code> if not
142      */
compareAndSwapLong(Object obj, long offset, long expectedValue, long newValue)143     public native boolean compareAndSwapLong(Object obj, long offset,
144             long expectedValue, long newValue);
145 
146     /**
147      * Performs a compare-and-set operation on an <code>Object</code>
148      * field (that is, a reference field) within the given object.
149      *
150      * @param obj non-null; object containing the field
151      * @param offset offset to the field within <code>obj</code>
152      * @param expectedValue expected value of the field
153      * @param newValue new value to store in the field if the contents are
154      * as expected
155      * @return <code>true</code> if the new value was in fact stored, and
156      * <code>false</code> if not
157      */
compareAndSwapObject(Object obj, long offset, Object expectedValue, Object newValue)158     public native boolean compareAndSwapObject(Object obj, long offset,
159             Object expectedValue, Object newValue);
160 
161     /**
162      * Gets an <code>int</code> field from the given object,
163      * using <code>volatile</code> semantics.
164      *
165      * @param obj non-null; object containing the field
166      * @param offset offset to the field within <code>obj</code>
167      * @return the retrieved value
168      */
getIntVolatile(Object obj, long offset)169     public native int getIntVolatile(Object obj, long offset);
170 
171     /**
172      * Stores an <code>int</code> field into the given object,
173      * using <code>volatile</code> semantics.
174      *
175      * @param obj non-null; object containing the field
176      * @param offset offset to the field within <code>obj</code>
177      * @param newValue the value to store
178      */
putIntVolatile(Object obj, long offset, int newValue)179     public native void putIntVolatile(Object obj, long offset, int newValue);
180 
181     /**
182      * Gets a <code>long</code> field from the given object,
183      * using <code>volatile</code> semantics.
184      *
185      * @param obj non-null; object containing the field
186      * @param offset offset to the field within <code>obj</code>
187      * @return the retrieved value
188      */
getLongVolatile(Object obj, long offset)189     public native long getLongVolatile(Object obj, long offset);
190 
191     /**
192      * Stores a <code>long</code> field into the given object,
193      * using <code>volatile</code> semantics.
194      *
195      * @param obj non-null; object containing the field
196      * @param offset offset to the field within <code>obj</code>
197      * @param newValue the value to store
198      */
putLongVolatile(Object obj, long offset, long newValue)199     public native void putLongVolatile(Object obj, long offset, long newValue);
200 
201     /**
202      * Gets an <code>Object</code> field from the given object,
203      * using <code>volatile</code> semantics.
204      *
205      * @param obj non-null; object containing the field
206      * @param offset offset to the field within <code>obj</code>
207      * @return the retrieved value
208      */
getObjectVolatile(Object obj, long offset)209     public native Object getObjectVolatile(Object obj, long offset);
210 
211     /**
212      * Stores an <code>Object</code> field into the given object,
213      * using <code>volatile</code> semantics.
214      *
215      * @param obj non-null; object containing the field
216      * @param offset offset to the field within <code>obj</code>
217      * @param newValue the value to store
218      */
putObjectVolatile(Object obj, long offset, Object newValue)219     public native void putObjectVolatile(Object obj, long offset,
220             Object newValue);
221 
222     /**
223      * Gets an <code>int</code> field from the given object.
224      *
225      * @param obj non-null; object containing the field
226      * @param offset offset to the field within <code>obj</code>
227      * @return the retrieved value
228      */
getInt(Object obj, long offset)229     public native int getInt(Object obj, long offset);
230 
231     /**
232      * Stores an <code>int</code> field into the given object.
233      *
234      * @param obj non-null; object containing the field
235      * @param offset offset to the field within <code>obj</code>
236      * @param newValue the value to store
237      */
putInt(Object obj, long offset, int newValue)238     public native void putInt(Object obj, long offset, int newValue);
239 
240     /**
241      * Lazy set an int field.
242      */
putOrderedInt(Object obj, long offset, int newValue)243     public native void putOrderedInt(Object obj, long offset, int newValue);
244 
245     /**
246      * Gets a <code>long</code> field from 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      * @return the retrieved value
251      */
getLong(Object obj, long offset)252     public native long getLong(Object obj, long offset);
253 
254     /**
255      * Stores a <code>long</code> field into the given object.
256      *
257      * @param obj non-null; object containing the field
258      * @param offset offset to the field within <code>obj</code>
259      * @param newValue the value to store
260      */
putLong(Object obj, long offset, long newValue)261     public native void putLong(Object obj, long offset, long newValue);
262 
263     /**
264      * Lazy set a long field.
265      */
putOrderedLong(Object obj, long offset, long newValue)266     public native void putOrderedLong(Object obj, long offset, long newValue);
267 
268     /**
269      * Gets an <code>Object</code> field from 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      * @return the retrieved value
274      */
getObject(Object obj, long offset)275     public native Object getObject(Object obj, long offset);
276 
277     /**
278      * Stores an <code>Object</code> field into the given object.
279      *
280      * @param obj non-null; object containing the field
281      * @param offset offset to the field within <code>obj</code>
282      * @param newValue the value to store
283      */
putObject(Object obj, long offset, Object newValue)284     public native void putObject(Object obj, long offset, Object newValue);
285 
286     /**
287      * Lazy set an object field.
288      */
putOrderedObject(Object obj, long offset, Object newValue)289     public native void putOrderedObject(Object obj, long offset,
290             Object newValue);
291 
292 
getBoolean(Object obj, long offset)293     public native boolean getBoolean(Object obj, long offset);
putBoolean(Object obj, long offset, boolean newValue)294     public native void putBoolean(Object obj, long offset, boolean newValue);
getByte(Object obj, long offset)295     public native byte getByte(Object obj, long offset);
putByte(Object obj, long offset, byte newValue)296     public native void putByte(Object obj, long offset, byte newValue);
getChar(Object obj, long offset)297     public native char getChar(Object obj, long offset);
putChar(Object obj, long offset, char newValue)298     public native void putChar(Object obj, long offset, char newValue);
getShort(Object obj, long offset)299     public native short getShort(Object obj, long offset);
putShort(Object obj, long offset, short newValue)300     public native void putShort(Object obj, long offset, short newValue);
getFloat(Object obj, long offset)301     public native float getFloat(Object obj, long offset);
putFloat(Object obj, long offset, float newValue)302     public native void putFloat(Object obj, long offset, float newValue);
getDouble(Object obj, long offset)303     public native double getDouble(Object obj, long offset);
putDouble(Object obj, long offset, double newValue)304     public native void putDouble(Object obj, long offset, double 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 
addressSize()351     public native int addressSize();
352 
pageSize()353     public native int pageSize();
354 
allocateMemory(long bytes)355     public native long allocateMemory(long bytes);
356 
freeMemory(long address)357     public native void freeMemory(long address);
358 
setMemory(long address, long bytes, byte value)359     public native void setMemory(long address, long bytes, byte value);
360 
getByte(long address)361     public native byte getByte(long address);
362 
putByte(long address, byte x)363     public native void putByte(long address, byte x);
364 
getShort(long address)365     public native short getShort(long address);
366 
putShort(long address, short x)367     public native void putShort(long address, short x);
368 
getChar(long address)369     public native char getChar(long address);
370 
putChar(long address, char x)371     public native void putChar(long address, char x);
372 
getInt(long address)373     public native int getInt(long address);
374 
putInt(long address, int x)375     public native void putInt(long address, int x);
376 
getLong(long address)377     public native long getLong(long address);
378 
putLong(long address, long x)379     public native void putLong(long address, long x);
380 
getFloat(long address)381     public native float getFloat(long address);
382 
putFloat(long address, float x)383     public native void putFloat(long address, float x);
384 
getDouble(long address)385     public native double getDouble(long address);
386 
putDouble(long address, double x)387     public native void putDouble(long address, double x);
388 
copyMemoryToPrimitiveArray(long srcAddr, Object dst, long dstOffset, long bytes)389     public native void copyMemoryToPrimitiveArray(long srcAddr,
390             Object dst, long dstOffset, long bytes);
391 
copyMemoryFromPrimitiveArray(Object src, long srcOffset, long dstAddr, long bytes)392     public native void copyMemoryFromPrimitiveArray(Object src, long srcOffset,
393             long dstAddr, long bytes);
394 
copyMemory(long srcAddr, long dstAddr, long bytes)395     public native void copyMemory(long srcAddr, long dstAddr, long bytes);
396 
397 
398     // The following contain CAS-based Java implementations used on
399     // platforms not supporting native instructions
400 
401     /**
402      * Atomically adds the given value to the current value of a field
403      * or array element within the given object {@code o}
404      * at the given {@code offset}.
405      *
406      * @param o object/array to update the field/element in
407      * @param offset field/element offset
408      * @param delta the value to add
409      * @return the previous value
410      * @since 1.8
411      */
412     // @HotSpotIntrinsicCandidate
getAndAddInt(Object o, long offset, int delta)413     public final int getAndAddInt(Object o, long offset, int delta) {
414         int v;
415         do {
416             v = getIntVolatile(o, offset);
417         } while (!compareAndSwapInt(o, offset, v, v + delta));
418         return v;
419     }
420 
421     /**
422      * Atomically adds the given value to the current value of a field
423      * or array element within the given object {@code o}
424      * at the given {@code offset}.
425      *
426      * @param o object/array to update the field/element in
427      * @param offset field/element offset
428      * @param delta the value to add
429      * @return the previous value
430      * @since 1.8
431      */
432     // @HotSpotIntrinsicCandidate
getAndAddLong(Object o, long offset, long delta)433     public final long getAndAddLong(Object o, long offset, long delta) {
434         long v;
435         do {
436             v = getLongVolatile(o, offset);
437         } while (!compareAndSwapLong(o, offset, v, v + delta));
438         return v;
439     }
440 
441     /**
442      * Atomically exchanges the given value with the current value of
443      * a field or array element within the given object {@code o}
444      * at the given {@code offset}.
445      *
446      * @param o object/array to update the field/element in
447      * @param offset field/element offset
448      * @param newValue new value
449      * @return the previous value
450      * @since 1.8
451      */
452     // @HotSpotIntrinsicCandidate
getAndSetInt(Object o, long offset, int newValue)453     public final int getAndSetInt(Object o, long offset, int newValue) {
454         int v;
455         do {
456             v = getIntVolatile(o, offset);
457         } while (!compareAndSwapInt(o, offset, v, newValue));
458         return v;
459     }
460 
461     /**
462      * Atomically exchanges the given value with the current value of
463      * a field or array element within the given object {@code o}
464      * at the given {@code offset}.
465      *
466      * @param o object/array to update the field/element in
467      * @param offset field/element offset
468      * @param newValue new value
469      * @return the previous value
470      * @since 1.8
471      */
472     // @HotSpotIntrinsicCandidate
getAndSetLong(Object o, long offset, long newValue)473     public final long getAndSetLong(Object o, long offset, long newValue) {
474         long v;
475         do {
476             v = getLongVolatile(o, offset);
477         } while (!compareAndSwapLong(o, offset, v, newValue));
478         return v;
479     }
480 
481     /**
482      * Atomically exchanges the given reference value with the current
483      * reference value of a field or array element within the given
484      * object {@code o} at the given {@code offset}.
485      *
486      * @param o object/array to update the field/element in
487      * @param offset field/element offset
488      * @param newValue new value
489      * @return the previous value
490      * @since 1.8
491      */
492     // @HotSpotIntrinsicCandidate
getAndSetObject(Object o, long offset, Object newValue)493     public final Object getAndSetObject(Object o, long offset, Object newValue) {
494         Object v;
495         do {
496             v = getObjectVolatile(o, offset);
497         } while (!compareAndSwapObject(o, offset, v, newValue));
498         return v;
499     }
500 
501 
502     /**
503      * Ensures that loads before the fence will not be reordered with loads and
504      * stores after the fence; a "LoadLoad plus LoadStore barrier".
505      *
506      * Corresponds to C11 atomic_thread_fence(memory_order_acquire)
507      * (an "acquire fence").
508      *
509      * A pure LoadLoad fence is not provided, since the addition of LoadStore
510      * is almost always desired, and most current hardware instructions that
511      * provide a LoadLoad barrier also provide a LoadStore barrier for free.
512      * @since 1.8
513      */
514     // @HotSpotIntrinsicCandidate
loadFence()515     public native void loadFence();
516 
517     /**
518      * Ensures that loads and stores before the fence will not be reordered with
519      * stores after the fence; a "StoreStore plus LoadStore barrier".
520      *
521      * Corresponds to C11 atomic_thread_fence(memory_order_release)
522      * (a "release fence").
523      *
524      * A pure StoreStore fence is not provided, since the addition of LoadStore
525      * is almost always desired, and most current hardware instructions that
526      * provide a StoreStore barrier also provide a LoadStore barrier for free.
527      * @since 1.8
528      */
529     // @HotSpotIntrinsicCandidate
storeFence()530     public native void storeFence();
531 
532     /**
533      * Ensures that loads and stores before the fence will not be reordered
534      * with loads and stores after the fence.  Implies the effects of both
535      * loadFence() and storeFence(), and in addition, the effect of a StoreLoad
536      * barrier.
537      *
538      * Corresponds to C11 atomic_thread_fence(memory_order_seq_cst).
539      * @since 1.8
540      */
541     // @HotSpotIntrinsicCandidate
fullFence()542     public native void fullFence();
543 }
544