UnSafe

源码:
http://www.docjar.com/html/api/sun/misc/Unsafe.java.html
API文档:
http://www.docjar.com/docs/api/sun/misc/Unsafe.html

我的分类:

1.声明
2.内存的操作
3.类相关操作
4.synchronization
5.park,unpark
6.CAS

其它人的idea:
https://www.cnblogs.com/mickole/articles/3757278.html

1.首先,unsafe 类,可以分配内存,可以释放内存。
2.可以定位对象某字段的内存位置,也可以修改对象的字段值,即使它是私有的;
3.挂起与恢复
4.CAS操作

声明

first we come to the declaration of the Usafe:
you can see the function in line 83,it will check the classLoader of the class who call it, if the one who call it have class loader ,it will throw "SecurityException". and that is the way it define if it is trusted code or not ,which annotated in the line 35.

the following passage have nice explain in " how to get the unsafe".
http://mishadoff.com/blog/java-magic-part-4-sun-dot-misc-dot-unsafe/

/**
   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
   41   public final class Unsafe {
   42   
   43       private static native void registerNatives();
   44       static {
   45           registerNatives();
   46           sun.reflect.Reflection.registerMethodsToFilter(Unsafe.class, "getUnsafe");
   47       }
   48   
   49       private Unsafe() {}
   50   
   51       private static final Unsafe theUnsafe = new Unsafe();
   52   
   83       public static Unsafe getUnsafe() {
   84           Class cc = sun.reflect.Reflection.getCallerClass(2);
   85           if (cc.getClassLoader() != null)
   86               throw new SecurityException("Unsafe");
   87           return theUnsafe;
   88       }

memory control

61 function explain here,the idea is all write in the annotation,include:
1.allocateMemory, reallocateMemory, freeMemory
2.get and put function
3.setMemory , copyMemory

import java.lang.reflect.Field;
import java.util.Arrays;
import sun.misc.Unsafe;

public class Test {
    private static int byteArrayBaseOffset;

    public static void main(String[] args) throws SecurityException,
            NoSuchFieldException, IllegalArgumentException,
            IllegalAccessException {
        /***
         * here shows how can we get the unsafe
         */
        Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe");
        theUnsafe.setAccessible(true);
        Unsafe UNSAFE = (Unsafe) theUnsafe.get(null);
        System.out.println(UNSAFE);

        /** in jdk8 there is 115 function, i count it myself ,i don't make sure i have't mistake here */

        Field sa = Integer.class.getDeclaredField("SIZE");
        System.out.println();
        long offset = UNSAFE.staticFieldOffset(sa);
        int value = UNSAFE.getInt(UNSAFE.staticFieldBase(sa),offset);
        System.out.println("value :" +value);


        /**
         * allocateMemory    allocate a new memory
         * reallocateMemory  will resize the memory size, if it fail to resize , throws OutOfMemoryError
         * freeMemory
         *
         * */


        /** in this case is show how can we use the given memory address to put value in ,and the influence in the memory
         *
         * 1.as you can see ,even you just have be allocate 1 memory ,you can use more memory ,but it is not safe at all ,
         * cause you can not forbid other thread or Object not to use the un-authority space,it will cause unexpected result
         *
         * so you know all the putXXX(long address,XXX value) and getXXX(long address) is couple
         * and how to use it.
         *
         * there are Int,Long,Byte,Boolean,Object,Float,Double,Short,Char  9  base type ,so there is 9 base function couple. 9*2=18
         *
         * there a
         *
         * */
        long am = UNSAFE.allocateMemory(1);//here i allocate a new memory
        UNSAFE.putInt(am,1);//i put a 0000 0001  in the first byte.
        System.out.println(UNSAFE.getInt(am)); //
        UNSAFE.putInt(am+1,2);//i put 0000 0010 int the second byte
        System.out.println("am+1 : "+UNSAFE.getInt(am+1)); // get the am+1 ,so it start from the second byte ,so the  output here is 2
        System.out.println("am+2 : "+ UNSAFE.getInt(am+2));//and here should be 0
        System.out.println("am :" + UNSAFE.getInt(am));// but if i start from the first byte it should be  0000 0001 0000 0010 so the result is 2*256 + 1= 512 +1 = 513,so the out put here should be 513

        UNSAFE.putInt(am+2,3);
        System.out.println(UNSAFE.getByte(am));
        System.out.println(UNSAFE.getByte(am+1));
        System.out.println(UNSAFE.getByte(am+2));
        System.out.println(UNSAFE.getByte(am+3));
        System.out.println(UNSAFE.getInt(am)); //65536 * 3 + 2*256 +1 = 196608 + 512 +1 = 197121

        UNSAFE.putInt(am+5,1);
        System.out.println(UNSAFE.getByte(am));
        System.out.println(UNSAFE.getByte(am+1));
        System.out.println(UNSAFE.getByte(am+2));
        System.out.println(UNSAFE.getByte(am+3));
        System.out.println(UNSAFE.getByte(am+4));
        System.out.println(UNSAFE.getInt(am));//so in here we can know the int take 4 bytes

        UNSAFE.freeMemory(am);
        /** like the case above,this case is almost the same. the only different is it use relative offset to describe the address
         *
         * use  object + offset to define a unique address
         *
         *  the follow case shows how it use.
         *  the same way , there are 9 base type ,so there is 9 base function couple, 9 * 2 = 18
         * */
        Integer integer = new Integer(10);
        System.out.println(integer);
        Field valueField = Integer.class.getDeclaredField("value");
        long a = UNSAFE.objectFieldOffset(valueField);
        UNSAFE.putInt(integer,a,11);
        System.out.println(UNSAFE.getInt(integer,a));
        System.out.println(integer);

        byte[] data = new byte[10];
        System.out.println(Arrays.toString(data));
        byteArrayBaseOffset = UNSAFE.arrayBaseOffset(byte[].class);
        System.out.println(byteArrayBaseOffset);
        UNSAFE.putByte(data, byteArrayBaseOffset, (byte) 1);
        UNSAFE.putByte(data, byteArrayBaseOffset + 5, (byte) 5);
        System.out.println(Arrays.toString(data));

        /**
         * ofcourse there also provide funciton volatile
         *
         * Fetches a reference value from a given Java variable, with volatile
         * load semantics. Otherwise identical to {@link #getObject(Object, long)}

         public native Object getObjectVolatile(Object o, long offset);

         * Stores a reference value into a given Java variable, with
         * volatile store semantics. Otherwise identical to {@link #putObject(Object, long, Object)}

         public native void    putObjectVolatile(Object o, long offset, Object x);
         *
         * the same way , there are 9 base type ,so there is 9 base function couple, 9 * 2 = 18
         */

        /**
         * there is another 2 interesting function which is use to set value in batch
         *
         public native void setMemory(Object o, long offset, long bytes, byte value);
         public native void setMemory(long address, long bytes, byte value);

         * use  o + offset or address to define the unique address "start postion"
         * and bytes and value ,means from the  "start postion" to "start postion"+bytes all the byte is set the value
         *
         * byte a = new byte[10];  or int[] a = new int[2];  can be realized by this function
         *
         *
         public native void copyMemory(Object srcBase, long srcOffset,
         Object destBase, long destOffset,
         long bytes);

         public void copyMemory(long srcAddress, long destAddress, long bytes) {
         copyMemory(null, srcAddress, null, destAddress, bytes);
         }
         *
         *  so there is alse function like that
         *  use  Base + offset or address to define the unique address "start postion" ."dest position" and copy the bytes long
         *  to the dest position
         * */
        /**
         *
         * util here we have kill 3 + 18*3 + 4 = 61 function
         * */
    }
}

appedency:
reference: http://www.jdon.com/performance/java-performance-optimizations-queue.html

使用Unsafe.putOrderedObject方法,这个方法在对低延迟代码是很有用的,它能够实现非堵塞的写入,这些写入不会被Java的JIT重新排序指令([instruction reordering](http://stackoverflow.com/questions/14321212/java-instruction-reordering-cache-in-threads)),
这样它使用快速的存储-存储(store-store) barrier, 
而不是较慢的存储-加载(store-load) barrier, (用在volatile的写操作上)
这种性能提升是有代价的,虽然便宜,也就是写后结果并不会被其他线程看到,甚至是自己的线程,通常是几纳秒后被其他线程看到,这个时间比较短,所以代价可以忍受。

类似Unsafe.putOrderedObject还有unsafe.putOrderedLong等方法,unsafe.putOrderedLong比使用 volatile long要快3倍左右。.

class

  804       /**
  805        * Tell the VM to define a class, without security checks.  By default, the
  806        * class loader and protection domain come from the caller's class.
  807        */
  808       public native Class defineClass(String name, byte[] b, int off, int len,
  809                                       ClassLoader loader,
  810                                       ProtectionDomain protectionDomain);
  811   
  812       public native Class defineClass(String name, byte[] b, int off, int len);
  813   
  814       /**
  815        * Define a class but do not make it known to the class loader or system dictionary.
  816        * <p>
  817        * For each CP entry, the corresponding CP patch must either be null or have
  818        * the a format that matches its tag:
  819        * <ul>
  820        * <li>Integer, Long, Float, Double: the corresponding wrapper object type from java.lang
  821        * <li>Utf8: a string (must have suitable syntax if used as signature or name)
  822        * <li>Class: any java.lang.Class object
  823        * <li>String: any object (not just a java.lang.String)
  824        * <li>InterfaceMethodRef: (NYI) a method handle to invoke on that call site's arguments
  825        * </ul>
  826        * @params hostClass context for linkage, access control, protection domain, and class loader
  827        * @params data      bytes of a class file
  828        * @params cpPatches where non-null entries exist, they replace corresponding CP entries in data
  829        */
  830       public native Class defineAnonymousClass(Class hostClass, byte[] data, Object[] cpPatches);

            public native Object allocateInstance(Class cls) throws InstantiationException;

synchronization

  838       /** Lock the object.  It must get unlocked via {@link #monitorExit}. */
  839       public native void monitorEnter(Object o);
  840   
  841       /**
  842        * Unlock the object.  It must have been locked via {@link
  843        * #monitorEnter}.
  844        */
  845       public native void monitorExit(Object o);
  846   
  847       /**
  848        * Tries to lock the object.  Returns true or false to indicate
  849        * whether the lock succeeded.  If it did, the object must be
  850        * unlocked via {@link #monitorExit}.
  851        */
  852       public native boolean tryMonitorEnter(Object o);
  853   
  854       /** Throw the exception without telling the verifier. */
  855       public native void throwException(Throwable ee);

thread park unpark

  960       /**
  961        * Unblock the given thread blocked on <tt>park</tt>, or, if it is
  962        * not blocked, cause the subsequent call to <tt>park</tt> not to
  963        * block.  Note: this operation is "unsafe" solely because the
  964        * caller must somehow ensure that the thread has not been
  965        * destroyed. Nothing special is usually required to ensure this
  966        * when called from Java (in which there will ordinarily be a live
  967        * reference to the thread) but this is not nearly-automatically
  968        * so when calling from native code.
  969        * @param thread the thread to unpark.
  970        *
  971        */
  972       public native void unpark(Object thread);
  973   
  974       /**
  975        * Block current thread, returning when a balancing
  976        * <tt>unpark</tt> occurs, or a balancing <tt>unpark</tt> has
  977        * already occurred, or the thread is interrupted, or, if not
  978        * absolute and time is not zero, the given time nanoseconds have
  979        * elapsed, or if absolute, the given deadline in milliseconds
  980        * since Epoch has passed, or spuriously (i.e., returning for no
  981        * "reason"). Note: This operation is in the Unsafe class only
  982        * because <tt>unpark</tt> is, so it would be strange to place it
  983        * elsewhere.
  984        */
  985       public native void park(boolean isAbsolute, long time);
  986   

CAS



  859        /* Atomically update Java variable to <tt>x</tt> if it is currently holding <tt>expected</tt>. 
              @return <tt>true</tt> if successful*/
  863       public final native boolean compareAndSwapObject(Object o, long offset,
  864                                                        Object expected,
  865                                                        Object x);

  872       public final native boolean compareAndSwapInt(Object o, long offset, int expected, int x);

  881       public final native boolean compareAndSwapLong(Object o, long offset, long expected, long x);
import java.lang.reflect.Field;
import sun.misc.Unsafe;


public class Test {
    private static Unsafe unsafe;

    public static void main(String[] args) throws Exception {
        try {
            //通过反射获取rt.jar下的Unsafe类
            Field field = Unsafe.class.getDeclaredField("theUnsafe");
            field.setAccessible(true);
            unsafe = (Unsafe) field.get(null);

            Integer target = 12;
            Field field1 = Integer.class.getDeclaredField("value");

            //compareAndSwapInt方法的属性分别是:目标对象实例,目标对象属性偏移量,当前预期值,要设的值.
            //compareAndSwapInt方法是通过反射修改对象的值,具体修改对象下面那个值,可以通过偏移量,对象字段的偏移量可以通过objectFieldOffset获取
            System.out.println(unsafe.compareAndSwapInt(target, unsafe.objectFieldOffset(field1), 1, 10));
            System.out.println(target);
            System.out.println(unsafe.compareAndSwapInt(target, unsafe.objectFieldOffset(field1), 12, 10));
            System.out.println(target);
        } catch (Exception e) {
            System.out.println("Get Unsafe instance occur error" + e);
        }
    }
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,132评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,802评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,566评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,858评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,867评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,695评论 1 282
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,064评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,705评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,915评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,677评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,796评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,432评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,041评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,992评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,223评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,185评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,535评论 2 343

推荐阅读更多精彩内容