南昌Java培训
达内南昌中心

0791-88193285

热门课程

达内:Java常量池与字符串intern简介

  • 时间:2015-11-16
  • 发布:南昌达内
  • 来源:达内培训


    达内java培训专家指出,Java应用程序运行时,Java虚拟机会保存一份内部的运行时常量池,它区别于class文件的常量池,是class文件常量池映射到虚拟机中的数据结构。 

    一、CONSTANT_Class入口解析

    数组类的符号解析较为特殊。若是基本类型数组,那么虚拟机将创建该基本类型的新数组类,并创建一个Class实例来代表该类型,数组类的定义类加载器为启动类加载器。若是引用类型的数组,那么在此之前还会进行引用类型的解析,数组类的定义类加载器为引用类型的定义类加载器。

    非数组类和接口的的解析将经历以下步骤:

    1.加载该类型及所有超类型

    2.检查访问权限

    3.类型校验

    4.类型准备

    5.类型解析

    6.类型初始化

    二、CONSTANT_Fieldref入口解析

    一个类型不含有其超类型所定义的字段,因此对目标字段的搜索将会从字段所 指向的类型开始,从该类型开始搜索,再递归搜索其所实现或扩展的接口,再递归搜索其超类,直至找到目标字段,并会将运行时常量池的该字段入口标记为已解 析,并在该常量池的数据上改为对这个字段的直接引用。

    三、CONSTANT_Methodref入口解析

    与字段的搜索类似,不尽相同,其搜索顺序将从该类型开始,再递归搜索其超类,在递归搜索其所实现或扩展的接口。

    四、CONSTANT_InterfaceMethodRef入口解析

    对接口方法的搜索就是从被解析的接口开始,向其超接口递归搜索。

    五、CONSTANT_String入口解析

    Java虚拟机会将字符串处理为一个字符串对象加以维护,而虚拟机所维护的就是一张 字符串池,它包含所有已拘留的字符串对象的引用。对CONSTANT_String常量池的解析首先就要查看字符串池中该字符串对象的引用是否存在, 如果存在则直接把常量池数据解析为该字符串对象的引用,若不存在,那么就需要根据这个字符串序列创建一个字符串对象,并将其引用加入到字符串池中,并将常 量池数据解析为该引用。

    也可以使用String对象的intern对象来拘留一个字符串(并非字符串对象),若该字符串池中存在对该字 符串序列的对象的引用,那么直接返回该引用即可,否则,将会拘留该字符串,但注意拘留返回的字符串对象引用将不会指向原String对象,因为原 String对象位于Java堆,而字符串池的对象是虚拟机所创建的,由虚拟机所维护。

    六、直接引用

    常量池解析最终将符号引用替换成为直接引用。指向类型、类变量和类方法的直接引用可能为在方法区的指针。而指向实例变量和实例方法的直接引用是从对象映像的开始到该实例变量或方法表的偏移。

    实例变量的组织方式为:从Object类开始到该实例的类型,将类中声明的实例变量按在class文件中出现的顺序依次放在对象映像中。

    实例方法的组织方式为:从Object类开始到该实例的类型,将类中声明的实例方法指针按在class文件中出现的顺序依次放在对象映像中。但对于重写的方法将出现在超类对应的位置。

    但是访问接口方法就不能简单地通过方法表的偏移量来进行访问,而必须搜索对象的类的方法表来找到该方法。

    比如Factory接口分别由A和B来实现其produce()方法,但由于A和B不能保证由同一个实现了Factory接口的超类派生,即有着同样的produce()方法偏移,那么就无法通过方法表的偏移来访问Factory的produce()方法。

    七、装载约束

    对于一个类型指向另一个类型的符号引用,如果引用的类型和被引用类型并非由同一个初始加载器加载,那么虚拟机就必须确保被引用类型在不同的命名空间中保持一致。这样就通过自定义ClassLoader来加载不受信类 型后,就不会发生解析对被引用类型的符号引用时,把受信的类型当做已经被解析过的不受信类型,从而调用了不受信类型的方法访问受信类型的受保护成员。


上一篇:提升 Java 中锁的性能有何方法
下一篇:java8 性能的五大优势

恭喜达内获得《产学合作协同育人项目合作伙伴奖》

达内Java大数据捷报频传,最高薪资15000元

中传学子参加达内Java培训,转身成为Java工程师月薪12.5K

本科生求职难参加达内Java培训,获11K高薪入职上海睿民

选择城市和中心
贵州省

广西省

海南省