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包的原理及分析