Home | History | Annotate | Download | only in misc
      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      */
     38     private Unsafe() {}
     39 
     40     /**
     41      * Gets the unique instance of this class. This is only allowed in
     42      * very limited situations.
     43      */
     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      */
     65     public long objectFieldOffset(Field field) {
     66         if (Modifier.isStatic(field.getModifiers())) {
     67             throw new IllegalArgumentException(
     68                     "valid for instance fields only");
     69         }
     70 
     71         return objectFieldOffset0(field);
     72     }
     73 
     74     /**
     75      * Helper for {@link #objectFieldOffset}, which does all the work,
     76      * assuming the parameter is deemed valid.
     77      *
     78      * @param field non-null; the instance field
     79      * @return the offset to the field
     80      */
     81     private static native long objectFieldOffset0(Field field);
     82 
     83     /**
     84      * Gets the offset from the start of an array object's memory to
     85      * the memory used to store its initial (zeroeth) element.
     86      *
     87      * @param clazz non-null; class in question; must be an array class
     88      * @return the offset to the initial element
     89      */
     90     public int arrayBaseOffset(Class clazz) {
     91         if (! clazz.isArray()) {
     92             throw new IllegalArgumentException(
     93                     "valid for array classes only");
     94         }
     95 
     96         return arrayBaseOffset0(clazz);
     97     }
     98 
     99     /**
    100      * Helper for {@link #arrayBaseOffset}, which does all the work,
    101      * assuming the parameter is deemed valid.
    102      *
    103      * @return the offset to the field
    104      */
    105     private static native int arrayBaseOffset0(Class clazz);
    106 
    107     /**
    108      * Gets the size of each element of the given array class.
    109      *
    110      * @param clazz non-null; class in question; must be an array class
    111      * @return > 0; the size of each element of the array
    112      */
    113     public int arrayIndexScale(Class clazz) {
    114         if (! clazz.isArray()) {
    115             throw new IllegalArgumentException(
    116                     "valid for array classes only");
    117         }
    118 
    119         return arrayIndexScale0(clazz);
    120     }
    121 
    122     /**
    123      * Helper for {@link #arrayIndexScale}, which does all the work,
    124      * assuming the parameter is deemed valid.
    125      *
    126      * @return the offset to the field
    127      */
    128     private static native int arrayIndexScale0(Class clazz);
    129 
    130     /**
    131      * Performs a compare-and-set operation on an <code>int</code>
    132      * field within the given object.
    133      *
    134      * @param obj non-null; object containing the field
    135      * @param offset offset to the field within <code>obj</code>
    136      * @param expectedValue expected value of the field
    137      * @param newValue new value to store in the field if the contents are
    138      * as expected
    139      * @return <code>true</code> if the new value was in fact stored, and
    140      * <code>false</code> if not
    141      */
    142     public native boolean compareAndSwapInt(Object obj, long offset,
    143             int expectedValue, int newValue);
    144 
    145     /**
    146      * Performs a compare-and-set operation on a <code>long</code>
    147      * field within the given object.
    148      *
    149      * @param obj non-null; object containing the field
    150      * @param offset offset to the field within <code>obj</code>
    151      * @param expectedValue expected value of the field
    152      * @param newValue new value to store in the field if the contents are
    153      * as expected
    154      * @return <code>true</code> if the new value was in fact stored, and
    155      * <code>false</code> if not
    156      */
    157     public native boolean compareAndSwapLong(Object obj, long offset,
    158             long expectedValue, long newValue);
    159 
    160     /**
    161      * Performs a compare-and-set operation on an <code>Object</code>
    162      * field (that is, a reference field) within the given object.
    163      *
    164      * @param obj non-null; object containing the field
    165      * @param offset offset to the field within <code>obj</code>
    166      * @param expectedValue expected value of the field
    167      * @param newValue new value to store in the field if the contents are
    168      * as expected
    169      * @return <code>true</code> if the new value was in fact stored, and
    170      * <code>false</code> if not
    171      */
    172     public native boolean compareAndSwapObject(Object obj, long offset,
    173             Object expectedValue, Object newValue);
    174 
    175     /**
    176      * Gets an <code>int</code> field from the given object,
    177      * using <code>volatile</code> semantics.
    178      *
    179      * @param obj non-null; object containing the field
    180      * @param offset offset to the field within <code>obj</code>
    181      * @return the retrieved value
    182      */
    183     public native int getIntVolatile(Object obj, long offset);
    184 
    185     /**
    186      * Stores an <code>int</code> field into the given object,
    187      * using <code>volatile</code> semantics.
    188      *
    189      * @param obj non-null; object containing the field
    190      * @param offset offset to the field within <code>obj</code>
    191      * @param newValue the value to store
    192      */
    193     public native void putIntVolatile(Object obj, long offset, int newValue);
    194 
    195     /**
    196      * Gets a <code>long</code> field from the given object,
    197      * using <code>volatile</code> semantics.
    198      *
    199      * @param obj non-null; object containing the field
    200      * @param offset offset to the field within <code>obj</code>
    201      * @return the retrieved value
    202      */
    203     public native long getLongVolatile(Object obj, long offset);
    204 
    205     /**
    206      * Stores a <code>long</code> field into the given object,
    207      * using <code>volatile</code> semantics.
    208      *
    209      * @param obj non-null; object containing the field
    210      * @param offset offset to the field within <code>obj</code>
    211      * @param newValue the value to store
    212      */
    213     public native void putLongVolatile(Object obj, long offset, long newValue);
    214 
    215     /**
    216      * Gets an <code>Object</code> field from the given object,
    217      * using <code>volatile</code> semantics.
    218      *
    219      * @param obj non-null; object containing the field
    220      * @param offset offset to the field within <code>obj</code>
    221      * @return the retrieved value
    222      */
    223     public native Object getObjectVolatile(Object obj, long offset);
    224 
    225     /**
    226      * Stores an <code>Object</code> field into the given object,
    227      * using <code>volatile</code> semantics.
    228      *
    229      * @param obj non-null; object containing the field
    230      * @param offset offset to the field within <code>obj</code>
    231      * @param newValue the value to store
    232      */
    233     public native void putObjectVolatile(Object obj, long offset,
    234             Object newValue);
    235 
    236     /**
    237      * Gets an <code>int</code> field from the given object.
    238      *
    239      * @param obj non-null; object containing the field
    240      * @param offset offset to the field within <code>obj</code>
    241      * @return the retrieved value
    242      */
    243     public native int getInt(Object obj, long offset);
    244 
    245     /**
    246      * Stores an <code>int</code> field into 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      * @param newValue the value to store
    251      */
    252     public native void putInt(Object obj, long offset, int newValue);
    253 
    254     /**
    255      * Lazy set an int field.
    256      */
    257     public native void putOrderedInt(Object obj, long offset, int newValue);
    258 
    259     /**
    260      * Gets a <code>long</code> field from the given object.
    261      *
    262      * @param obj non-null; object containing the field
    263      * @param offset offset to the field within <code>obj</code>
    264      * @return the retrieved value
    265      */
    266     public native long getLong(Object obj, long offset);
    267 
    268     /**
    269      * Stores a <code>long</code> field into 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      * @param newValue the value to store
    274      */
    275     public native void putLong(Object obj, long offset, long newValue);
    276 
    277     /**
    278      * Lazy set a long field.
    279      */
    280     public native void putOrderedLong(Object obj, long offset, long newValue);
    281 
    282     /**
    283      * Gets an <code>Object</code> field from the given object.
    284      *
    285      * @param obj non-null; object containing the field
    286      * @param offset offset to the field within <code>obj</code>
    287      * @return the retrieved value
    288      */
    289     public native Object getObject(Object obj, long offset);
    290 
    291     /**
    292      * Stores an <code>Object</code> field into the given object.
    293      *
    294      * @param obj non-null; object containing the field
    295      * @param offset offset to the field within <code>obj</code>
    296      * @param newValue the value to store
    297      */
    298     public native void putObject(Object obj, long offset, Object newValue);
    299 
    300     /**
    301      * Lazy set an object field.
    302      */
    303     public native void putOrderedObject(Object obj, long offset,
    304             Object 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      */
    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      */
    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      */
    349     public native Object allocateInstance(Class<?> c);
    350 }
    351