Chinaunix首页 | 论坛 | 博客
  • 博客访问: 621697
  • 博文数量: 69
  • 博客积分: 1891
  • 博客等级: 上尉
  • 技术积分: 1359
  • 用 户 组: 普通用户
  • 注册时间: 2010-11-20 23:38
文章分类

全部博文(69)

文章存档

2012年(46)

2011年(23)

分类: Java

2012-09-04 07:39:25

3、接下来就是constant_pool
     前面讲过,常量池里存放的是字面常量和符号引用。

     1、字面常量
     字面常量分别包含String,Integer,Float,Long,Double这几个类型,这些字段都是以二进制的方式存储的,所以存储的时候,只要指定类型、长度和对应的值即可。这样的话,那这些基本的常量就可以采用如下的结构来表示:

点击(此处)折叠或打开

  1. CONSTANT_XXX{
  2.           type;//该常量的类型
  3.           length;//该常量的长度,以字节为单位
  4.           byte[];//该常量的二进制表示,包含length个字节
  5.      }

     不过对于Integer、Float、Long和Double这些常量的长度是固定不变的,所以可以省去以节省空间;但是字符串常量的长度是不能省的。
     
     2、符号引用

     符号引用包含三种特殊的字符串,它们分别是:
     1、全局限定名 当一个常量表示类或者接口的时候,需要指定类的全局限定名,在class文件中,全局限定名的点用斜杠来代替,例如java.lang.Object的全局限定名为java/lang/Object
     2、简单名称 类的字段名或者方法名以简单名称的方式存在常量池里,例如上面Hello.test字段在class文件里会存有形如“test”的简单名称。
   3、描述符   除了成员变量的名称和方法,class文件里还要存储对应的描述符。描述符在class文件里以一种简化的方式表示,这样就可以减少class文件的大小。

      成员变量的描述符和方法的修饰符可以使用下面的语法来表示:

点击(此处)折叠或打开

  1. FieldDescriptor:
  2.           FieldType

  3.      ComponentType:
  4.           FieldType

  5.       FieldType:
  6.           BaseType
  7.           ObjectType
  8.           ArrayType

  9.      BaseType:
  10.           B
  11.           C
  12.           D
  13.           F
  14.           I
  15.           J
  16.           S
  17.           Z

  18.      ObjectType:
  19.           L Classname ;

  20.      ArrayType:
  21.           [ComponentType

  22.      MethodDescriptor:
  23.           ( ParameterDescriptor* ) ReturnDescriptor

  24.      ParameterDescriptor:
  25.           FieldType

  26.      ReturnDescriptor:
  27.           FieldType
  28.           VoidDescriptor

  29.     VoidDescriptor:
  30.           V                  
     简单来说,对于成员变量而言,它的描述符是它的类型,类型又分为:BasicType,ObjectType和ArrayType。

  •      BasicType指的是byte,char,double,float,int,long,short,boolean这几种基本类型,它们分别用B、C、D、F、I、L、S、Z来表示。
  •      ObjectType指的是对象类型,也就是说该成员变量的类型是一个Java类,那么这种类型就用L加上Classname表示。例如一个类型为java.lang.String的变量,它的描述符为Ljava/lang/String。
  •      ArrayType指的是列表类型,也就是说这个成员变量是个数组。对于数组类型,每一个维度用一个前置的“[”来描述。例如一个定义为"java.lang.String[][]"的变量的描述符为[[java/lang/String;对于一个定义为“int[]”的变量,它的描述符表示为“[I”。

     对于方法而言,它的描述符是先参数列表,后返回值的方式组成。参数列表按照声明的顺序排列,每个参数的格式和成员变量的格式一样。所有的参数放在一个括号里面和返回值进行分隔。返回值的格式也和成员变量的格式一样,不过返回值多了一个void类型,用“V”来表示。
     例如,对于void test()方法,它的描述符表示为“()V”,而对于java.lang.String test(int[],int index)方法,它的描述符表示为“([II)Ljava/lang/String”。
     这些特殊的字符串在常量池里是采取引用的方式来表示的,它们有如下的结构:  

点击(此处)折叠或打开

  1. CONSTANT_XXX{
  2.           type;//字符串的类型
  3.           index;//对应的值的引用
  4.      }

     3、字符串的存储方式

     在class文件里,字符串也是采用引用的方式进行存储的,它的引用指向该字符串对应的UTF-8的一个变体的表示。

点击(此处)折叠或打开

  1. CONSTANT_XXX{
  2.           type;//字符串的类型
  3.           index;//对应的值的引用
  4.      }
    对应的UTF-8表示的结构

点击(此处)折叠或打开

  1. CONSTANT_UTF8{
  2.           type;
  3.           length;
  4.           value[];
  5.      }

     4、常量的基本格式
     由上面的分析可以知道,常量的结构都是以常量的类型开始,然后才是具体的数据。这样的话,常量池里的变量都是如下的结构:

点击(此处)折叠或打开

  1. cp_info {
  2.                u1 tag;
  3.                u1 info[];
  4.           }

     其中的tag就是常量对应的类型,主要有以下几个值:
 后面的info[]字段,代表具体结构的数据,需要按照对应的结构来进行分析
   

阅读(3127) | 评论(0) | 转发(1) |
给主人留下些什么吧!~~