JVM总结四

平台无关性和语言无关性 class文件格式

class文件是严格按照顺序紧凑排列的,不包含任何分隔符,没有空隙,超过8位的数据项,采用高位在前的方式排列

伪结构体,两种数据结构,无符号数和表,u1,u2,u4,u8,1,2,4,8个字节的无符号数,表示数字,数量,索引和UTF-8编码的字符串;表是由多个无符号数或者其他表构成的复杂数据类型。整个class file就是一个表

结构:

1.魔数 u4

2.minor version u2

3.major version u2

4.常量池数据项数量

5.上一项-1个常量数据(第0项空出来,是为了满足有些指向常量池索引值的数据需要表达“不引用”任何一个常量池项目,把索引值设为0)。常量池主要存放两大类数据,字面量和符号引用。字面量就是java中的常量,如文本字符串,被声明为final的常量。符号引用:类和接口的全限定名,字段的名称和描述符,方法的名称和描述符。java编译没有连接步骤,class文件中不会保存方法和字段的最终内存布局信息,在虚拟机加载后,在类解析或者运行时在转换到直接引用。每一个常量池数据项都是一个常量池数据表(有11种类型,如整型,浮点等字面量,字符串,类,方法,字段的符号引用等)javap –verbose 查看字节码。编译器会添加一些常量项如<init>,V等,会被后面的方法表,属性表所引用

6.访问标志 u2 是表示类和接口的访问信息,如是类还是接口,是否为public,是否为final等,目前有8个,可支持32个标志位,通过把标识为真的值取或运算得出结果如0x0001|0x0020=0x0021

7.类索引,父类索引和接口索引集合

通过索引到常量池class_info,在到utf-8 string,接口多个前面也有接口个数字段

8字段个数和字段表

字段表主要内容,访问标志,和类的访问标志相似,后面两项是简单名称和描述符,都是指向常量池的引用。全限定名称是吧类全名的.换成/,而简单名称就是没有类型和参数修饰的方法或字段名称。描述符的作用是用来描述字段的类型,方法的参数列表和返回值,引用类型是L+全限定名,数组每一个纬度前置一个[。最后是属性个数和属性表,如果有常量,一般有constantvalue属性

不包含父类的字段,但会有可能增加不存在与代码的字段,如内部类的父类引用的字段,并且字节码里面,如果字段描述符不同,字段名称可以相同,但java语言不允许字段的重载,所以不允许重名

9.方法个数和方法表

和字段表一样,访问标识,简单名称和描述符,方法描述符按照参数列表顺序,放在小括号中,后面是返回值类型,方法体内的字节码描述放在属性表中的code属性中,如果子类没有覆盖父类的方法,方法集合中不会包含父类的方法,但是会增加一些不存在的方法,如类构造器 <clinit>和实例构造器<init>.java中的重载,除了方法名相同外,需要一个与原方法不同的特征签名,java代码层面的特征签名只包括方法名,方法参数顺序和参数类型;但是字节码层面的特征签名还包括返回值类型

10.类的属性表个数和属性表

属性表可以在class,方法表,字段表中

code属性

在方法表中,存放代码编译成的字节码指令,code属性表主要的max_stack是操作数栈的最大深度,max_locals是局部变量表的大小(实例变量的this参数,catch中的exception参数都包含),code长度(理论上可以达到232-1,但是虚拟机规定不能超过65535,一般不编写太大的方法都不会有问题,但是注意在编译很大的jsp文件时可能会出现)和code2进制流,每一条虚拟机质量是一个字节,但是有些指令可以带参数。code之后的是方法中的显示异常处理表,有四个属性start,end,handler,catchtype,表示从start到end如果抛出catchtype对应的异常或者子类,则跳转到handler指令去处理。如果catchtype的值为0,则代表任何的异常情况都跳转到handler处理

EXCEPTIONS属性

这个代表的是方法抛出的checked异常列表,即throws后面的异常

linenumbertable

字节码指令和源代码行之间的对应关系,主要影响是抛出异常堆栈时会没有对应的行号,可以通过javac –g:none或者-g:lines取消或者生成

localvariabletable和localvariabletypetable

描述栈帧中局部变量表中的变量与java源码中变量之间的关系,由于泛型的出现,所以有variabletype的出现,如果没有这个信息,当其他人引用这个方法时,会把参数列表用arg0,arg1之类的占位符来代替

sourcefile

得到该class文件的源代码文件的名称

constantvalue

只有静态变量可以使用这项属性,javac要求final和static同时使用才会使用constantvalue属性,实例变量赋值在<init>方法,而类变量可以在<clinit>或者constantvalue赋值,属性值是一个常量池索引,所以只支持基本类型和string

innerclasses

内部类与宿主类之间的关系,编译器会为宿主类和内部类都生成innerclasses属性

deprecated和synthetic

都是标志,没有属性值

前一个可用于类,字段,方法,表示不再推荐使用,使用注解进行设置

后一个代表方法或者字段不是源码直接产生的,而是编译器添加的,jdk1.5之后增加了一个访问标志同样的作用

signature属性,因为描述符不能完全表达泛型,保存泛型信息

stackmaptable属性,加快虚拟机的校验,将校验需要的信息写入class

注解相关的属性等

你可能感兴趣的:(JVM总结四)