Unsafe

Unsafe


一、总结

1.jdk 1.8.0

2.不可仿照 AtomicInteger 的方式直接调用 Unfase
// 声明全局的静态变量,运行时会出现异常 SecurityException("Unsafe")
private static final Unsafe unsafe = Unsafe.getUnsafe();


3.从源码注释得知,这个类是用于执行低级别、不安全操作的方法集合。尽管这个类和所有的方法都是公开的(public),但是这个类的使用仍然受限,你无法在自己的java程序中直接使用该类,因为只有授信的代码才能获得该类的实例。所以我们平时的代码是无法使用这个类的,因为其设计的操作过于偏底层,如若操作不慎可能会带来很大的灾难,所以直接禁止普通代码的访问,当然JDK使用是没有问题的。

二、源码分析

// 获取类中属性在对象中的地址的偏移量,即以堆中开辟的对象空间的起始地址为基址
// 相对于此值的偏移地址;根据对象的起始位置和偏移量可确认该属性在堆中的存放位置
// 进而可以获取到此属性的值
public native long objectFieldOffset(Field field);


// 示例
// 通过获取类中属性的偏移量,配合对象的地址,获取该属性的值
import java.lang.reflect.Field;

import sun.misc.Unsafe;

public class ObjectMain {

	private int a ;
	private int b ;
	private String str ;

	/**
	 * @param args
	 * @throws SecurityException 
	 * @throws NoSuchFieldException 
	 * @throws IllegalAccessException 
	 * @throws IllegalArgumentException 
	 */
	public static void main(String[] args) throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException {
		Unsafe unsafe = getUnsafeInstance();
		// 获取实例字段的偏移地址,偏移最小的那个字段(仅挨着头部)就是对象头的大小  
		long objectFieldOffseta = unsafe.objectFieldOffset(ObjectMain.class.getDeclaredField("a"));
		long objectFieldOffsetb = unsafe.objectFieldOffset(ObjectMain.class.getDeclaredField("b"));
		System.out.println(objectFieldOffseta);
		System.out.println(objectFieldOffsetb);
		// 通过偏移量和对象的基址
		ObjectMain main = new ObjectMain();
		main.setA(10);
		Integer resultA = unsafe.getInt(main,objectFieldOffseta);
		System.out.println(resultA);
	}
	
	/**
	 * 通过反射获取Unsafe类中 theUnsafe 属性
	 * @return
	 * @throws SecurityException
	 * @throws NoSuchFieldException
	 * @throws IllegalArgumentException
	 * @throws IllegalAccessException
	 */
	private static Unsafe getUnsafeInstance() throws SecurityException, NoSuchFieldException, IllegalArgumentException,  
    IllegalAccessException {  
		Field theUnsafeInstance = Unsafe.class.getDeclaredField("theUnsafe");  
		theUnsafeInstance.setAccessible(true);  
		return (Unsafe) theUnsafeInstance.get(Unsafe.class);  
	}  
	
	public int getA() {
		return a;
	}

	public void setA(int a) {
		this.a = a;
	}

	public int getB() {
		return b;
	}
	
	public void setB(int b) {
		this.b = b;
	}

	public String getStr() {
		return str;
	}

	public void setStr(String str) {
		this.str = str;
	}

}



    public static Unsafe getUnsafe()
    {
        Class class1 = Reflection.getCallerClass();
        if(!VM.isSystemDomainLoader(class1.getClassLoader()))
            throw new SecurityException("Unsafe");
        else
            return theUnsafe;
    }

    private static final Unsafe theUnsafe;
    static 
    {
        registerNatives();
        Reflection.registerMethodsToFilter(sun/misc/Unsafe, new String[] {
            "getUnsafe"
        });
        theUnsafe = new Unsafe();
    }
    
    private static native void registerNatives();



博文参考:
java对象的内存布局(二):利用sun.misc.Unsafe获取类字段的偏移地址和读取字段的值
Java之美[从菜鸟到高手演练]之atomic包的原理及分析

猜你喜欢

转载自mingyundezuoan.iteye.com/blog/2401185