可以做到你想做到的一切的 java unsafe

2017-01-11

自己由于对netty底层代码的一些拜读,还有一切里面的代码有些是借鉴github大神,自己整理出来为了以后可以用的,分享出来,大家学习学习。程序的至理名言:越是地层越是高效,上层越是抽象越是简单。所以分享下java unsafe这个类。编辑器编译不会通过的,要调一下编辑器的配置,具体我也忘啦,google在手天下我有,自己搞搞。
这个是测试类,里面只有几个内容,有点没体现unsafe的强大,自己可以发掘下。

package com.demo;

import java.lang.reflect.Field;
import sun.misc.Unsafe;
public class UnsafeTest {
      public static void main(String[] args) throws Exception{

           Unsafe unsafe =UnsafeHelper.getUnsafe();
           long address=unsafe.allocateMemory(1);
           unsafe.putChar(address,'a');
           //可以取到任何一个类的实例,不管有什么样的构造器。
           Student student=(Student)unsafe.allocateInstance(Student.class);
           System.out.println(UnsafeHelper.toAddress(student));
              student.setName("lisi");
              student.setAge(18);
              for(Field field:Student.class.getDeclaredFields()){  
                  System.out.println(field.getName()+":对应的内存偏移地址"+unsafe.objectFieldOffset(field));  
              }  
              System.out.println("-------"+unsafe.getAddress(UnsafeHelper.toAddress(student))+"------------");  
              int ageOffset= 8; 
              //下面演示的是变量的原子操作,不可打断。
              //修改内存偏移地址为8的值(age),返回true,说明通过内存偏移地址修改age的值成功  
              System.out.println(unsafe.compareAndSwapInt(student, ageOffset, 18, 20));  
              System.out.println("age修改后的值:"+student.getAge());  
              System.out.println("-------------------");  

              //修改内存偏移地址为8的值,但是修改后不保证立马能被其他的线程看到。  
              unsafe.putOrderedInt(student, 8, 33);  
              System.out.println("age修改后的值:"+student.getAge());  
              System.out.println("-------------------");  

              //修改内存偏移地址为12的值,volatile修饰,修改能立马对其他线程可见  
              unsafe.putObjectVolatile(student, 12, "han mei");  
              System.out.println("name修改后的值:"+unsafe.getObjectVolatile(student, 12));
       }
    }
    class Student{
        private String name;

        private int age;

        private Student(){
            System.out.println("============");
        }



        public int getAge() {
            return age;
        }



        public void setAge(int age) {
            this.age = age;
        }



        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

    }

无所不能的unsafe工具类,这个是重点可以好好自己上手试试。

package com.demo;

import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.HashSet;

import sun.misc.Unsafe;

public class UnsafeHelper {
    private static final Unsafe unsafe = createUnsafe();

      private static Unsafe createUnsafe() {
        try {
          Field field = Unsafe.class.getDeclaredField("theUnsafe");
          field.setAccessible(true);
          return (Unsafe) field.get(null);
        } catch (Exception e) {
          throw new RuntimeException("Can't use unsafe", e);
        }
      }

      public static Unsafe getUnsafe() {
        return unsafe;
      }

      public static long toAddress(Object obj) {
            Object[] array = new Object[] {obj};
            long baseOffset = unsafe.arrayBaseOffset(Object[].class);
            return normalize(unsafe.getInt(array, baseOffset));
          }
      private static long normalize(int value) {
            if (value >= 0) {
              return value;
            }
            return (~0L >>> 32) & value;
          }
      public static long sizeOf(Object o) {
            Unsafe u = getUnsafe();
            HashSet<Field> fields = new HashSet<Field>();
            Class<?> c = o.getClass();
            while (c != Object.class) {
                for (Field f : c.getDeclaredFields()) {
                    if ((f.getModifiers() & Modifier.STATIC) == 0) {
                        fields.add(f);
                    }
                }
                c = c.getSuperclass();
            }
            // get offset
            long maxSize = 0;
            for (Field f : fields) {
                long offset = u.objectFieldOffset(f);
                if (offset > maxSize) {
                    maxSize = offset;
                }
            }
            return ((maxSize/8) + 1) * 8;   // padding
        }

        public  static Object fromAddress(long address) {
                Object[] array = new Object[] {null};
                long baseOffset = getUnsafe().arrayBaseOffset(Object[].class);
                getUnsafe().putLong(array, baseOffset, address);
                return array[0];
            }

        public  static Object shallowCopy(Object obj) {
                long size = sizeOf(obj);
                long start = toAddress(obj);
                long address = getUnsafe().allocateMemory(size);
                getUnsafe().copyMemory(start, address, size);
                return fromAddress(address);
            }
}

第一次写,请见谅,就想整理出来,那天要用的时候可以找到。

顶部