自己由于对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);
}
}
第一次写,请见谅,就想整理出来,那天要用的时候可以找到。