• 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.annotation.optimization.FastNative;
29 import dalvik.system.VMStack;
30 import java.lang.reflect.Field;
31 import java.lang.reflect.Modifier;
32 
33 /**
34  * A collection of methods for performing low-level, unsafe operations.
35  * Although the class and all methods are public, use of this class is
36  * limited because only trusted code can obtain instances of it.
37  *
38  * @author John R. Rose
39  * @see #getUnsafe
40  */
41 public final class Unsafe {
42     /** Traditional dalvik name. */
43     private static final Unsafe THE_ONE = new Unsafe();
44 
45     private static final Unsafe theUnsafe = THE_ONE;
46     public static final int INVALID_FIELD_OFFSET   = -1;
47 
48     /**
49      * This class is only privately instantiable.
50      */
Unsafe()51     private Unsafe() {}
52 
53     /**
54      * Gets the unique instance of this class. This is only allowed in
55      * very limited situations.
56      */
getUnsafe()57     public static Unsafe getUnsafe() {
58         /*
59          * Only code on the bootclasspath is allowed to get at the
60          * Unsafe instance.
61          */
62         ClassLoader calling = VMStack.getCallingClassLoader();
63         if ((calling != null) && (calling != Unsafe.class.getClassLoader())) {
64             throw new SecurityException("Unsafe access denied");
65         }
66 
67         return THE_ONE;
68     }
69 
70     /**
71      * Gets the raw byte offset from the start of an object's memory to
72      * the memory used to store the indicated instance field.
73      *
74      * @param field non-null; the field in question, which must be an
75      * instance field
76      * @return the offset to the field
77      */
objectFieldOffset(Field field)78     public long objectFieldOffset(Field field) {
79         if (Modifier.isStatic(field.getModifiers())) {
80             throw new IllegalArgumentException("valid for instance fields only");
81         }
82         return field.getOffset();
83     }
84 
85     /**
86      * Gets the offset from the start of an array object's memory to
87      * the memory used to store its initial (zeroeth) element.
88      *
89      * @param clazz non-null; class in question; must be an array class
90      * @return the offset to the initial element
91      */
arrayBaseOffset(Class clazz)92     public int arrayBaseOffset(Class clazz) {
93         Class<?> component = clazz.getComponentType();
94         if (component == null) {
95             throw new IllegalArgumentException("Valid for array classes only: " + clazz);
96         }
97         return getArrayBaseOffsetForComponentType(component);
98     }
99 
100     /**
101      * Gets the size of each element of the given array class.
102      *
103      * @param clazz non-null; class in question; must be an array class
104      * @return &gt; 0; the size of each element of the array
105      */
arrayIndexScale(Class clazz)106     public int arrayIndexScale(Class clazz) {
107       Class<?> component = clazz.getComponentType();
108       if (component == null) {
109           throw new IllegalArgumentException("Valid for array classes only: " + clazz);
110       }
111       return getArrayIndexScaleForComponentType(component);
112     }
113 
114     @FastNative
getArrayBaseOffsetForComponentType(Class component_class)115     private static native int getArrayBaseOffsetForComponentType(Class component_class);
116     @FastNative
getArrayIndexScaleForComponentType(Class component_class)117     private static native int getArrayIndexScaleForComponentType(Class component_class);
118 
119     /**
120      * Performs a compare-and-set operation on an <code>int</code>
121      * field within the given object.
122      *
123      * @param obj non-null; object containing the field
124      * @param offset offset to the field within <code>obj</code>
125      * @param expectedValue expected value of the field
126      * @param newValue new value to store in the field if the contents are
127      * as expected
128      * @return <code>true</code> if the new value was in fact stored, and
129      * <code>false</code> if not
130      */
131     @FastNative
compareAndSwapInt(Object obj, long offset, int expectedValue, int newValue)132     public native boolean compareAndSwapInt(Object obj, long offset,
133             int expectedValue, int newValue);
134 
135     /**
136      * Performs a compare-and-set operation on a <code>long</code>
137      * field within the given object.
138      *
139      * @param obj non-null; object containing the field
140      * @param offset offset to the field within <code>obj</code>
141      * @param expectedValue expected value of the field
142      * @param newValue new value to store in the field if the contents are
143      * as expected
144      * @return <code>true</code> if the new value was in fact stored, and
145      * <code>false</code> if not
146      */
147     @FastNative
compareAndSwapLong(Object obj, long offset, long expectedValue, long newValue)148     public native boolean compareAndSwapLong(Object obj, long offset,
149             long expectedValue, long newValue);
150 
151     /**
152      * Performs a compare-and-set operation on an <code>Object</code>
153      * field (that is, a reference field) within the given object.
154      *
155      * @param obj non-null; object containing the field
156      * @param offset offset to the field within <code>obj</code>
157      * @param expectedValue expected value of the field
158      * @param newValue new value to store in the field if the contents are
159      * as expected
160      * @return <code>true</code> if the new value was in fact stored, and
161      * <code>false</code> if not
162      */
163     @FastNative
compareAndSwapObject(Object obj, long offset, Object expectedValue, Object newValue)164     public native boolean compareAndSwapObject(Object obj, long offset,
165             Object expectedValue, Object newValue);
166 
167     /**
168      * Gets an <code>int</code> field from the given object,
169      * using <code>volatile</code> semantics.
170      *
171      * @param obj non-null; object containing the field
172      * @param offset offset to the field within <code>obj</code>
173      * @return the retrieved value
174      */
175     @FastNative
getIntVolatile(Object obj, long offset)176     public native int getIntVolatile(Object obj, long offset);
177 
178     /**
179      * Stores an <code>int</code> field into the given object,
180      * using <code>volatile</code> semantics.
181      *
182      * @param obj non-null; object containing the field
183      * @param offset offset to the field within <code>obj</code>
184      * @param newValue the value to store
185      */
186     @FastNative
putIntVolatile(Object obj, long offset, int newValue)187     public native void putIntVolatile(Object obj, long offset, int newValue);
188 
189     /**
190      * Gets a <code>long</code> field from 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      * @return the retrieved value
196      */
197     @FastNative
getLongVolatile(Object obj, long offset)198     public native long getLongVolatile(Object obj, long offset);
199 
200     /**
201      * Stores a <code>long</code> field into the given object,
202      * using <code>volatile</code> semantics.
203      *
204      * @param obj non-null; object containing the field
205      * @param offset offset to the field within <code>obj</code>
206      * @param newValue the value to store
207      */
208     @FastNative
putLongVolatile(Object obj, long offset, long newValue)209     public native void putLongVolatile(Object obj, long offset, long newValue);
210 
211     /**
212      * Gets an <code>Object</code> field from 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      * @return the retrieved value
218      */
219     @FastNative
getObjectVolatile(Object obj, long offset)220     public native Object getObjectVolatile(Object obj, long offset);
221 
222     /**
223      * Stores an <code>Object</code> field into the given object,
224      * using <code>volatile</code> semantics.
225      *
226      * @param obj non-null; object containing the field
227      * @param offset offset to the field within <code>obj</code>
228      * @param newValue the value to store
229      */
230     @FastNative
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      */
241     @FastNative
getInt(Object obj, long offset)242     public native int getInt(Object obj, long offset);
243 
244     /**
245      * Stores an <code>int</code> field into the given object.
246      *
247      * @param obj non-null; object containing the field
248      * @param offset offset to the field within <code>obj</code>
249      * @param newValue the value to store
250      */
251     @FastNative
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      */
257     @FastNative
putOrderedInt(Object obj, long offset, int newValue)258     public native void putOrderedInt(Object obj, long offset, int newValue);
259 
260     /**
261      * Gets a <code>long</code> field from the given object.
262      *
263      * @param obj non-null; object containing the field
264      * @param offset offset to the field within <code>obj</code>
265      * @return the retrieved value
266      */
267     @FastNative
getLong(Object obj, long offset)268     public native long getLong(Object obj, long offset);
269 
270     /**
271      * Stores a <code>long</code> field into 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      * @param newValue the value to store
276      */
277     @FastNative
putLong(Object obj, long offset, long newValue)278     public native void putLong(Object obj, long offset, long newValue);
279 
280     /**
281      * Lazy set a long field.
282      */
283     @FastNative
putOrderedLong(Object obj, long offset, long newValue)284     public native void putOrderedLong(Object obj, long offset, long newValue);
285 
286     /**
287      * Gets an <code>Object</code> field from the given object.
288      *
289      * @param obj non-null; object containing the field
290      * @param offset offset to the field within <code>obj</code>
291      * @return the retrieved value
292      */
293     @FastNative
getObject(Object obj, long offset)294     public native Object getObject(Object obj, long offset);
295 
296     /**
297      * Stores an <code>Object</code> field into the given object.
298      *
299      * @param obj non-null; object containing the field
300      * @param offset offset to the field within <code>obj</code>
301      * @param newValue the value to store
302      */
303     @FastNative
putObject(Object obj, long offset, Object newValue)304     public native void putObject(Object obj, long offset, Object newValue);
305 
306     /**
307      * Lazy set an object field.
308      */
309     @FastNative
putOrderedObject(Object obj, long offset, Object newValue)310     public native void putOrderedObject(Object obj, long offset,
311             Object newValue);
312 
313 
314     @FastNative
getBoolean(Object obj, long offset)315     public native boolean getBoolean(Object obj, long offset);
316     @FastNative
putBoolean(Object obj, long offset, boolean newValue)317     public native void putBoolean(Object obj, long offset, boolean newValue);
318     @FastNative
getByte(Object obj, long offset)319     public native byte getByte(Object obj, long offset);
320     @FastNative
putByte(Object obj, long offset, byte newValue)321     public native void putByte(Object obj, long offset, byte newValue);
322     @FastNative
getChar(Object obj, long offset)323     public native char getChar(Object obj, long offset);
324     @FastNative
putChar(Object obj, long offset, char newValue)325     public native void putChar(Object obj, long offset, char newValue);
326     @FastNative
getShort(Object obj, long offset)327     public native short getShort(Object obj, long offset);
328     @FastNative
putShort(Object obj, long offset, short newValue)329     public native void putShort(Object obj, long offset, short newValue);
330     @FastNative
getFloat(Object obj, long offset)331     public native float getFloat(Object obj, long offset);
332     @FastNative
putFloat(Object obj, long offset, float newValue)333     public native void putFloat(Object obj, long offset, float newValue);
334     @FastNative
getDouble(Object obj, long offset)335     public native double getDouble(Object obj, long offset);
336     @FastNative
putDouble(Object obj, long offset, double newValue)337     public native void putDouble(Object obj, long offset, double newValue);
338 
339     /**
340      * Parks the calling thread for the specified amount of time,
341      * unless the "permit" for the thread is already available (due to
342      * a previous call to {@link #unpark}. This method may also return
343      * spuriously (that is, without the thread being told to unpark
344      * and without the indicated amount of time elapsing).
345      *
346      * <p>See {@link java.util.concurrent.locks.LockSupport} for more
347      * in-depth information of the behavior of this method.</p>
348      *
349      * @param absolute whether the given time value is absolute
350      * milliseconds-since-the-epoch (<code>true</code>) or relative
351      * nanoseconds-from-now (<code>false</code>)
352      * @param time the (absolute millis or relative nanos) time value
353      */
park(boolean absolute, long time)354     public void park(boolean absolute, long time) {
355         if (absolute) {
356             Thread.currentThread().parkUntil$(time);
357         } else {
358             Thread.currentThread().parkFor$(time);
359         }
360     }
361 
362     /**
363      * Unparks the given object, which must be a {@link Thread}.
364      *
365      * <p>See {@link java.util.concurrent.locks.LockSupport} for more
366      * in-depth information of the behavior of this method.</p>
367      *
368      * @param obj non-null; the object to unpark
369      */
unpark(Object obj)370     public void unpark(Object obj) {
371         if (obj instanceof Thread) {
372             ((Thread) obj).unpark$();
373         } else {
374             throw new IllegalArgumentException("valid for Threads only");
375         }
376     }
377 
378     /**
379      * Allocates an instance of the given class without running the constructor.
380      * The class' <clinit> will be run, if necessary.
381      */
allocateInstance(Class<?> c)382     public native Object allocateInstance(Class<?> c);
383 
384     @FastNative
addressSize()385     public native int addressSize();
386 
387     @FastNative
pageSize()388     public native int pageSize();
389 
390     @FastNative
allocateMemory(long bytes)391     public native long allocateMemory(long bytes);
392 
393     @FastNative
freeMemory(long address)394     public native void freeMemory(long address);
395 
396     @FastNative
setMemory(long address, long bytes, byte value)397     public native void setMemory(long address, long bytes, byte value);
398 
399     @FastNative
getByte(long address)400     public native byte getByte(long address);
401 
402     @FastNative
putByte(long address, byte x)403     public native void putByte(long address, byte x);
404 
405     @FastNative
getShort(long address)406     public native short getShort(long address);
407 
408     @FastNative
putShort(long address, short x)409     public native void putShort(long address, short x);
410 
411     @FastNative
getChar(long address)412     public native char getChar(long address);
413 
414     @FastNative
putChar(long address, char x)415     public native void putChar(long address, char x);
416 
417     @FastNative
getInt(long address)418     public native int getInt(long address);
419 
420     @FastNative
putInt(long address, int x)421     public native void putInt(long address, int x);
422 
423     @FastNative
getLong(long address)424     public native long getLong(long address);
425 
426     @FastNative
putLong(long address, long x)427     public native void putLong(long address, long x);
428 
429     @FastNative
getFloat(long address)430     public native float getFloat(long address);
431 
432     @FastNative
putFloat(long address, float x)433     public native void putFloat(long address, float x);
434 
435     @FastNative
getDouble(long address)436     public native double getDouble(long address);
437 
438     @FastNative
putDouble(long address, double x)439     public native void putDouble(long address, double x);
440 
441     @FastNative
copyMemoryToPrimitiveArray(long srcAddr, Object dst, long dstOffset, long bytes)442     public native void copyMemoryToPrimitiveArray(long srcAddr,
443             Object dst, long dstOffset, long bytes);
444 
445     @FastNative
copyMemoryFromPrimitiveArray(Object src, long srcOffset, long dstAddr, long bytes)446     public native void copyMemoryFromPrimitiveArray(Object src, long srcOffset,
447             long dstAddr, long bytes);
448 
449     @FastNative
copyMemory(long srcAddr, long dstAddr, long bytes)450     public native void copyMemory(long srcAddr, long dstAddr, long bytes);
451 
452 
453     // The following contain CAS-based Java implementations used on
454     // platforms not supporting native instructions
455 
456     /**
457      * Atomically adds the given value to the current value of a field
458      * or array element within the given object {@code o}
459      * at the given {@code offset}.
460      *
461      * @param o object/array to update the field/element in
462      * @param offset field/element offset
463      * @param delta the value to add
464      * @return the previous value
465      * @since 1.8
466      */
467     // @HotSpotIntrinsicCandidate
getAndAddInt(Object o, long offset, int delta)468     public final int getAndAddInt(Object o, long offset, int delta) {
469         int v;
470         do {
471             v = getIntVolatile(o, offset);
472         } while (!compareAndSwapInt(o, offset, v, v + delta));
473         return v;
474     }
475 
476     /**
477      * Atomically adds the given value to the current value of a field
478      * or array element within the given object {@code o}
479      * at the given {@code offset}.
480      *
481      * @param o object/array to update the field/element in
482      * @param offset field/element offset
483      * @param delta the value to add
484      * @return the previous value
485      * @since 1.8
486      */
487     // @HotSpotIntrinsicCandidate
getAndAddLong(Object o, long offset, long delta)488     public final long getAndAddLong(Object o, long offset, long delta) {
489         long v;
490         do {
491             v = getLongVolatile(o, offset);
492         } while (!compareAndSwapLong(o, offset, v, v + delta));
493         return v;
494     }
495 
496     /**
497      * Atomically exchanges the given value with the current value of
498      * a field or array element within the given object {@code o}
499      * at the given {@code offset}.
500      *
501      * @param o object/array to update the field/element in
502      * @param offset field/element offset
503      * @param newValue new value
504      * @return the previous value
505      * @since 1.8
506      */
507     // @HotSpotIntrinsicCandidate
getAndSetInt(Object o, long offset, int newValue)508     public final int getAndSetInt(Object o, long offset, int newValue) {
509         int v;
510         do {
511             v = getIntVolatile(o, offset);
512         } while (!compareAndSwapInt(o, offset, v, newValue));
513         return v;
514     }
515 
516     /**
517      * Atomically exchanges the given value with the current value of
518      * a field or array element within the given object {@code o}
519      * at the given {@code offset}.
520      *
521      * @param o object/array to update the field/element in
522      * @param offset field/element offset
523      * @param newValue new value
524      * @return the previous value
525      * @since 1.8
526      */
527     // @HotSpotIntrinsicCandidate
getAndSetLong(Object o, long offset, long newValue)528     public final long getAndSetLong(Object o, long offset, long newValue) {
529         long v;
530         do {
531             v = getLongVolatile(o, offset);
532         } while (!compareAndSwapLong(o, offset, v, newValue));
533         return v;
534     }
535 
536     /**
537      * Atomically exchanges the given reference value with the current
538      * reference value of a field or array element within the given
539      * object {@code o} at the given {@code offset}.
540      *
541      * @param o object/array to update the field/element in
542      * @param offset field/element offset
543      * @param newValue new value
544      * @return the previous value
545      * @since 1.8
546      */
547     // @HotSpotIntrinsicCandidate
getAndSetObject(Object o, long offset, Object newValue)548     public final Object getAndSetObject(Object o, long offset, Object newValue) {
549         Object v;
550         do {
551             v = getObjectVolatile(o, offset);
552         } while (!compareAndSwapObject(o, offset, v, newValue));
553         return v;
554     }
555 
556 
557     /**
558      * Ensures that loads before the fence will not be reordered with loads and
559      * stores after the fence; a "LoadLoad plus LoadStore barrier".
560      *
561      * Corresponds to C11 atomic_thread_fence(memory_order_acquire)
562      * (an "acquire fence").
563      *
564      * A pure LoadLoad fence is not provided, since the addition of LoadStore
565      * is almost always desired, and most current hardware instructions that
566      * provide a LoadLoad barrier also provide a LoadStore barrier for free.
567      * @since 1.8
568      */
569     // @HotSpotIntrinsicCandidate
570     @FastNative
loadFence()571     public native void loadFence();
572 
573     /**
574      * Ensures that loads and stores before the fence will not be reordered with
575      * stores after the fence; a "StoreStore plus LoadStore barrier".
576      *
577      * Corresponds to C11 atomic_thread_fence(memory_order_release)
578      * (a "release fence").
579      *
580      * A pure StoreStore fence is not provided, since the addition of LoadStore
581      * is almost always desired, and most current hardware instructions that
582      * provide a StoreStore barrier also provide a LoadStore barrier for free.
583      * @since 1.8
584      */
585     // @HotSpotIntrinsicCandidate
586     @FastNative
storeFence()587     public native void storeFence();
588 
589     /**
590      * Ensures that loads and stores before the fence will not be reordered
591      * with loads and stores after the fence.  Implies the effects of both
592      * loadFence() and storeFence(), and in addition, the effect of a StoreLoad
593      * barrier.
594      *
595      * Corresponds to C11 atomic_thread_fence(memory_order_seq_cst).
596      * @since 1.8
597      */
598     // @HotSpotIntrinsicCandidate
599     @FastNative
fullFence()600     public native void fullFence();
601 }
602