Field unsafeField = Unsafe.class.getDeclaredField("theUnsafe"); unsafeField.setAccessible(true); Unsafe unsafe = (Unsafe) unsafeField.get(null);
二.Unsafe自己对调用者的检查
public static Unsafe getUnsafe() { Class cc = sun.reflect.Reflection.getCallerClass(2); if (cc.getClassLoader() != null) throw new SecurityException("Unsafe"); return theUnsafe; }
getCallerClass调用栈帧,从0开始。
0:getCallerClass方法的Reflection类;
1:getUnsafe方法的Unsafe类;
2:调用getUnsafe方法的所属类
比如:
public static void main(String[] args) throws Exception { Class cc = sun.reflect.Reflection.getCallerClass(1); //0:getCallerClass方法的Reflection类,1:main方法的所属类 }
cc.getClassLoader()!= null 用于判断类加载器是否是bootstrap classloader。
1.Bootstrap ClassLoader - GetClassLoader的返回值为Null,是JVM的C++源码,Ext ClassLoader 的Parent,主要负责jdk_home/lib目录下的核心 api 或 -Xbootclasspath 选项指定的jar包装入工作;
2.System ClassLoader - GetClassLoader返回值为SystemClassLoader.
主要负责java -classpath/-Djava.class.path所指的目录下的类与jar包装入工作
3.Ext ClassLoader - 是AppClassLoader 的Parent 返回Ext ClassLoader
主要负责jdk_home/lib/ext目录下的jar包或-Djava.ext.dirs 指定目录下的jar包装入工作。
4.App ClassLoader - 返回AppClassLoader,主要负责加载用户类。
(后续在继续分析ClassLoader机制)
三:public native int getInt(Object o, long offset);注释中提到三种情况
第一种场景:The offset was obtained from {@link #objectFieldOffset} on the {@link java.lang.reflect.Field} of some Java field and the object referred to by
o
is of a class compatible with that field's class.
private int offset = 10; public static void main(String[] args) throws Exception { long fieldOffset = unsafe.objectFieldOffset(Main.class.getDeclaredField("offset")) ; int fieldValue = unsafe.getInt(new Main(), fieldOffset); }
第二种场景:The offset and object reference
o
(either null or non-null) were both obtained via{@link #staticFieldOffset} and {@link #staticFieldBase} (respectively) from the reflective {@link Field} representation of some Java field.
private static int staticoffset = 20; public static void main(String[] args) throws Exception { Field staticField = Main.class.getDeclaredField("staticoffset"); long staticFieldOffset = unsafe.staticFieldOffset(staticField); Object obj = unsafe.staticFieldBase(staticField); int staticFieldValue =unsafe.getInt(obj, staticFieldOffset); }
第三种场景:The object referred to by
o
is an array, and the offset is an integer of the form B+N*S
, where N
is a valid index into the array, and B
and S
are the values obtained by {@link #arrayBaseOffset} and {@link #arrayIndexScale} (respectively) from the array's class. The value referred to is the N
th element of the array.
public static void main(String[] args) throws Exception { int [] intarray = new int[3]; intarray[0] = 10; intarray[1] = 20; intarray[2] = 30; int arrayOffset = unsafe.arrayBaseOffset(intarray.getClass()); int arrayScale = unsafe.arrayIndexScale(intarray.getClass()); long lg = arrayOffset + 2 * arrayScale; int arrayValue = unsafe.getInt(intarray, lg); }