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