java安全基础-Unsafe

全限定名为sun.misc.Unsafe,是Java底层的API提供的一个类,它提供非常底层的内存、CAS、线程程度、类、对象等操作A,是一个可以直接操作内存,不用构造器、不需要任何访问权限检查就可以创建对象的类

sun.mics.Unsafe

Unsafe源码如下:

public final class Unsafe {
    private static final Unsafe theUnsafe;
    private Unsafe() {
    }
    @CallerSensitive
    public static Unsafe getUnsafe() {
        Class var0 = Reflection.getCallerClass();
        // 检查调用类的加载器是不是Bootstrap,也就是null
        if (!VM.isSystemDomainLoader(var0.getClassLoader())) {
            throw new SecurityException("Unsafe");
        } else {
            return theUnsafe;
        }
    }
 }

上述代码可以看出,Unsafe唯一的构造器也是private,没法通过new实例化

虽然getUnsafe()是一个public方法,但是它会检查调用getUsafe()类的加载器是不是Bootstrap类加载器,但是我们定义类的默认加载器是AppClassLoader,所以会直接抛出异常。
检查类加载器代码如下:

// bootstrap加载器负责加载rt.jar,不是java编写,所以是null
public static boolean isSystemDomainLoader(ClassLoader var0) {
    return var0 == null;
}

获取Unsafe对象

虽然不能直接实例化获取Unsafe对象,但我们可以尝试通过反射从theUnsafe和构造器入手创建实例化对象:

  • 方法一:反射获取字段即theUnsafe属性,就相当于获取到了Unsafe对象
  • 方法二:反射获取构造器,再获取Unsafe实例

demo如下:

import sun.misc.Unsafe;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;

public class TemporaryFiles {
    public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException, NoSuchFieldException {
        Class unsafeClass = Unsafe.class;
        // 第一种方式:通过构造器获取Unsafe实例
        Constructor constructor = Unsafe.class.getDeclaredConstructor();
        constructor.setAccessible(true);
        Unsafe unsafe1 = (Unsafe) constructor.newInstance();
        System.out.println(unsafe1);

        // 第二种方法:通过字段获取Unsafe实例
        Field theUnsafe = unsafeClass.getDeclaredField("theUnsafe");
        theUnsafe.setAccessible(true);
        Unsafe unsafe2 = (Unsafe) theUnsafe.get(null);
        System.out.println(unsafe2);
    }
}
/*
输出:
sun.misc.Unsafe@4554617c
sun.misc.Unsafe@1540e19d
*/
posted @ 2024-06-06 14:21  Yuy0ung  阅读(50)  评论(0)    收藏  举报