欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Unsafe 博客分类: sun.misc Unsafe 

程序员文章站 2024-02-05 17:45:22
...
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包的原理及分析
相关标签: Unsafe