一种获取Java中sun.misc.Unsafe实例的方法

来源 :中小企业管理与科技·下旬刊 | 被引量 : 0次 | 上传用户:luoqiuqiu80
下载到本地 , 更方便阅读
声明 : 本文档内容版权归属内容提供方 , 如果您对本文有版权争议 , 可与客服联系进行内容授权或下架
论文部分内容阅读
  摘要:sun.misc.Unsafe类属于Java语言中基础类库的一部分,可以实现常规Java语言编程难以完成的任务,但它没有在JDK文档中公开,而且被限制使用。文中通过分析该类的设计模式,指出起限制作用的代码,并使用Java语言的反射机制获取到实例,同时给出具体代码以及使用条件。
  
  0 引言
  Java语言中,sun.misc.Unsafe类(下文简称Unsafe类)在基础类库中被大量使用,“扮演”着重要的角色。例如,java.math.BigInteger类在反序列化的过程中使用Unsafe类设置两个常量域,这两个常量域分别表示前者的符号和大小;java.util.concurrent.atomic包下的类使用Unsafe类实现原子操作。
  Unsafe类的主要功能是执行底层调用,以本地代码的形式实现常规Java语言编程难以完成的任务。典型应用包括分配内存并以指针的形式进行操作、以偏移量的形式访问成员域、设置或取消线程的等待状态以及调用基于硬件的比较并交换指令等。可见,在编程过程中使用Unsafe类,有助于开发功能强大的应用。但是,Sun Micro System公司并沒有开放相应的API,而且限制开发人员获取实例。在此,笔者从该类的设计模式入手,介绍实例化过程中面临的问题,并以反射机制获取其实例。
  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.Reflection.Class,参数值为1返回Unsafe.Class,参数值为2时返回调用getUnsafe方法的类的Class实例,即引用cc。
  根据JDK文档中的描述,只有在被引导类加载器加载的类、基本数据类型以及void类型的Class实例上调用getClassLoader方法,返回值才能为null。当开发人员直接调用getUnsafe方法时,cc所代表的类必然由开发人员编写,不会被引导类加载器加载,cc.getClassLoader()的返回结果必然不为null,则if语句条件成立,抛出异常,调用失败。
  由此可见,getUnsafe方法只能被Java基础类库中已有的类调用,开发人员不能直接使用。
  3 使用反射机制获取Unsafe实例
  Java虚拟机在启动时,BootStrap加载器负责加载dt.jar中的类,Unsafe类就在其中,当开发人员的代码执行时,Unsafe类中的私有静态最终成员域theUnsafe已经被初始化,此时可以使用反射机制获取后者的引用,变相地获得Unsafe实例。需要说明的是,通过反射机制访问私有成员,需要取消Java语言访问检查。代码如下:
  import java.lang.reflect.Field;
  import sun.misc.Unsafe;
  public class UnsafeSupport {
  private static Unsafe unsafe;
  static {
  try{
  Field field = Unsafe.class.getDeclaredField("theUnsafe");
  field.setAccessible(true);
  unsafe = (Unsafe) field.get(null);
  } catch(Exception e) {
  System.out.println("访问失败");
  }
  }
  public static Unsafe getInstance() {
  return unsafe;
  }
  }
  以上代码中,UnsafeSupport类封装了获取Unsafe实例的代码,通过公共静态方法getInstance返回结果,同样采用单一设计模式。在try代码块中,首先获取Unsafe类中theUnsafe成员域的Field对象;其次通过field.setAccessible(true)取消Java语言访问检查;最终,通过反射取得目标成员域的引用。
  4 总结
  Unsafe类封装了强大的功能,其中很多方法涉及到指针等底层操作,就像它的名称一样,会带来一定的不安全因素,这也是它不被公开的原因之一,在使用前要对代码做仔细的检查和测试。文中给出的方法需要取消Java语言访问检查,在不被允许的应用环境下会导致异常,使用前还需要进行全面的分析和评估。
  参考文献:
  [1]马朝晖,陈美红.Java语言导学.北京:机械工业出版社.2003,1.
  [2]陈昊鹏.Java编程思想.北京:机械工业出版社.2007,6.
  [3]陈昊鹏.JAVA核心技术卷II:高级特性.北京:机械工业出版社.2008,12.
  [4]阎宏.Java与模式.北京:电子工业出版社.2002,10.
  [5]耿祥义,张跃平.Java设计模式.北京:清华大学出版社.2009,5.
  [6]O’Reilly Taiwan公司.JAVA技术手册.南京:东南大学出版社.2006,10.
其他文献
摘要:案例教学是一种启发式、探究式的教学模式,能多方面提高学生的能力和综合素质,但由于在案例教学中师生角色定位不准,严重影响了案例教学的效果,本文从这个角度出发对教学中师生扮演的角色进行了探析。  关键词:案例教学 角色 探析  案例教学方法最早出现的时代可以追溯到古希腊、古罗马。大约公元1870年前后,美国哈佛法学院前院长克里斯托弗·哥伦布·郎道尔将这种方法运用到法学教育中,开创了案例教学法的应
随着我国煤炭开采业的迅速发展,综合采掘机械化程度的不断提升,胶带输送机在煤矿井上、下得到了广泛的应用。近年来,随着输送机使用数量不断增加,运输距离的增长,胶带输送机的事故
SDH光传输设备,是一种将复接、线路传输及交换功能融为一体、并由统一网管系统操作的综合信息传送网络。SDH光传输设备可实现网络有效管理、实时业务监控、动态网络维护、不同
为确认防治褐飞虱适宜器械及用水量,分别选用手动喷雾器、电动喷雾器、弥雾机3种不同的施药器械,在4代褐飞虱低龄若虫盛期喷雾施药,考察40%吡蚜·呋虫胺水分散粒剂对稻飞
摘要:本文对我国北方的学生宿舍空气品质及对学生健康的影响进行了研究。结果表明建筑潮湿表征、噪音敏感性(OR=8.957)、近12个月过敏性鼻炎(OR=7.410)、近12个月呼吸系统疾病(OR=0.081)、户外运动时间(OR=0.327)是5个影响病态建筑综合症的重要影响因素  关键词:空气品质 病态建筑综合症 logistic回归分析  我国学生宿舍空间比较狭小,人员密集,住宿期为2~4年,人
随着计算机监控系统的广泛应用与快速发展,一些小水电也进行了计算机监控系统技术改造,不仅提高了小水电的自动化水平,而且提高了小水电的可靠性,安全性和经济效益。本文分析了新
鉴于现行阳历存在着一定缺陷,笔者特制定《中华龙历》对其进行完善改良。具体内容为:设定立春日(阳历2月4日)为岁首,使年度划分与季节顺应;重新分配月份天数,设四五六七八月
氟噻唑吡乙酮是首个哌啶基噻唑异唑啉类杀菌剂,对卵菌纲病害具有保护和治疗活性,且持效期长。文中介绍了氟噻唑吡乙酮的理化性质、作用机理、合成方法,重点介绍了其开发进展
摘要:随着我国高校教育体制的转变,我国的高校财务管理也发展了重要的改变,由过去的记账式财务管理向现在的财务成本控制转变,可以说我国的高校财务管理出现了很好的转变,但是就目前我国的高校财务的特点,国家对高校实行了“核定收支,定额或定向补助,超支不补,节余留用”的预算管理模式,但其仍局限于计算预算收支余超的阶段,这样就会使得我国的高校成本核算出现一些弊端,本文就是通过对我国的高校财务成本的核算控制的实
本文主要简要介绍了SCP一体机的各部分功能及其控制方式,并且简要叙述了在使用过程中出现的一些问题及解决办法。摸索总结出一套合适的管理方法。