【编者按】网学网JAVA频道为大家收集整理了“ 一种获取Java中sun.misc.Unsafe实例的方法 “提供大家参考,希望对大家有所帮助!
1 Unsafe类的设计模式面向对象的编程语言中,最重要的方法莫过于类的构造方法,它决定了实例的初始状态。Unsafe类在声明构造方法时,只使用如下一行代码:private Unsafe(){}由于构造方法只有一个,类在实例化时就必须执行。但是,该构造方法被声明为私有型,外界访问者不能调用,Unsafe类就必须自己调用构造方法完成初始化。代码如下:private static final Unsafe theUnsafe=new Unsafe();public static Unsafe getUnsafe(){Class cc=sun.reflect.Reflection.getCallerClass(2);if(cc.getClassLoader()!=null)throw new SecurityException("Unsafe");return theUnsafe;}从代码中可以明显得出,Unsafe类采用了单例设计模式,以确保最多只有一个实例,而且外界必须使用getUnsafe方法才能得到。
2不开放的getUnsafe方法上文代码中,getUnsafe内部使用到sun.reflect.Reflection类的getCallerClass方法,后者也没有被公开,其返回值是Class类型,可以反映出当前虚拟机中类的调用关系,参数用于指定返回值距离调用栈顶端的距离。例如,参数值为0时返回sun.reflect.Re-flection.Class,参数值为1返回Unsafe.Class,参数值为2时返回调用getUnsafe方法的类的Class实例,即引用cc。根据JDK文档中的描述,只有在被引导类加载器加载的类、基本数据类型以及void类型的Class实例上调用getClassLoader方法,返回值才能为null。
当开发人员直接调用getUnsafe方法时,cc所代表的类必然由开发人员编写,不会被引导类加载器加载,cc.getClassLoader()的返回结果必然不为null,则if语句条件成立,抛出异常,调用失败。由此可见,getUnsafe方法只能被Java基础类库中已有的类调用,开发人员不能直接使用。使用反射机制获取Unsafe实例Java虚拟机在启动时,BootStrap加载器负责加载dt.jar中的类,Unsafe类就在其中,当开发人员的代码执行时,Unsafe类中的私有静态最终成员域theUnsafe已经被初始化,此时可以使用反射机制获取后者的引用,变相地获得Unsafe实例。需要说明的是,通过反射机制访问私有成员,需要取消Java语言访问检查。