博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
(十八)属性表
阅读量:5878 次
发布时间:2019-06-19

本文共 4157 字,大约阅读时间需要 13 分钟。

一、概念

上一章节讲述了方法表,方法体的内容就存放在属性表的“Code”中,如下图。

在Class文件、字段表和方法表都可以携带自己的属性信息,这个信息用属性表进行描述,用于描述某些场景专有的信息。

与Class文件中其它数据项对长度、顺序、格式的严格要求不同,属性表集合不要求其中包含的属性表具有严格的顺序,并且只要属性的名称不与已有的属性名称重复,任何人实现的编译器可以向属性表中写入自己定义的属性信息。虚拟机在运行时会忽略不能识别的属性,为了能正确解析Class文件,虚拟机规范中预定义了虚拟机实现必须能够识别的9项属性。

 

 

二、Code 属性

java程序方法体中的代码经过javac编译器处理后,最终变为字节码指令存储在Code属性内。

Code属性出现在方法表的属性集合中,抽象类和接口不存在code属性。 

code属性是class类文件中最重要的属性。class文件可以分为代码(code,方法体里面的Java代码)和元数据(Metadata,包括类,字段,方法定义及其他信息)两部分,code属性描述代码,其他数据项都用于描述元数据。

 

 以上一章节的代码为例:

public class Test {    private int getAge(int userId){        return 10;    }        public Object getUserName(String sex,Object obj){        return "admin";    }}

用javap查看常量池,如下:

C:\Users\Administrator\Desktop>javap -verbose Test.classClassfile /C:/Users/Administrator/Desktop/Test.class  Last modified 2018-5-19; size 364 bytes  MD5 checksum f8f46b81a72fa2dea893f30738c9bd8c  Compiled from "Test.java"public class Test  minor version: 0  major version: 52  flags: ACC_PUBLIC, ACC_SUPERConstant pool:   #1 = Methodref          #4.#15         // java/lang/Object."
":()V #2 = String #16 // admin #3 = Class #17 // Test #4 = Class #18 // java/lang/Object #5 = Utf8
#6 = Utf8 ()V #7 = Utf8 Code #8 = Utf8 LineNumberTable #9 = Utf8 getAge #10 = Utf8 (I)I #11 = Utf8 getUserName #12 = Utf8 (Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/Object; #13 = Utf8 SourceFile #14 = Utf8 Test.java #15 = NameAndType #5:#6 // "
":()V #16 = Utf8 admin #17 = Utf8 Test #18 = Utf8 java/lang/Object{ public Test(); descriptor: ()V flags: ACC_PUBLIC Code: stack=1, locals=1, args_size=1 0: aload_0 1: invokespecial #1 // Method java/lang/Object."
":()V 4: return LineNumberTable: line 2: 0 public java.lang.Object getUserName(java.lang.String, java.lang.Object); descriptor: (Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/Object; flags: ACC_PUBLIC Code: stack=1, locals=3, args_size=3 0: ldc #2 // String admin 2: areturn LineNumberTable: line 9: 0}SourceFile: "Test.java"

 

  •  Class文件对应的Code属性代码,如下图:

 

  1.  如图中的1.attribute_name_inde = 0x0007 = #7 查看常量池可知 #7 = “Code”
  2.    如图中的2  attribute_length =0x0000001d=29 ,属性值的长度为29
  3.  如图中的3 max_stack=1,表示所需操作数栈的深度的最大值为1,方法执行的任何时刻,操作数栈都不会超过这个深度。虚拟机运行时需要根据这个值分配栈帧。 
  4.  如图中的4 max_locals=1,表示说明需要的局部变量槽位为1。代表局部变量表所需的存储空间,单位为Slot(插槽),Slot是虚拟机为局部变量分配内存空间使用的最小单位。长度不超过32位的数据类型占用1个Slot(byte,char,float,int,short,boolean,returnAddress),64位的数据类型(long和double)占用2个Slot。Slot可以重用。当代码执行超过局部变量的作用域时,Solt可以被其他局部变量使用。
  5. 如图中的5 code_length 代表字节码长度。
  6.  如图中的6 ,code用于存储字节码指令的一系列字节流。每个字节指令是一个u1数据类型(1bit).虚拟机读取到一个一个字节码时,就可以找出对应的这个字节码是什么指令。java虚拟机最多可以有256条指令,现在有200多条指令。虚拟机读取到后会顺序依次的读取之后的5个字节,并根据字节码指令表()翻译为对应的字节码指令。 过程如下: 
    •   读入2A,对应指令为aload_0,将第0个Slot槽位为reference类型的本地变量推送到栈的顶端。
    •        读入B7,对应指令为invokespecial,将栈顶的reference类型的数据所指向的对象作为方法的接收者,调用此对象的实例构造方法。这条指令带有一个u2类型的参数,为具体调用的哪一个方法,指向常量池中一个 
      CONSTANT_Methodref_info类型常量,即此方法的符号应用。 
    • 读入00 01,0x0001对应为常量池第1个常量,为实例构造器init方法的符号引用
#1 = Methodref          #4.#15         // java/lang/Object."
":()V
    • 读入B1,对应指令为return,含义为返回此方法,返回值为void。这条指令执行完后当前方法结束。

          7. 如图中的7,异常表对Code属性来说不是必须存在, 在本实例中为0x0000,说明不存在异常表。

          8.  如图中的8,attributes_count=1,Code表带有一个属性。

          9。 如图中的9,Code表的属性为0x0008 =8 #8= " LineNumberTable"  ,  LineNumberTable属性用于描述Java源代码行号与字节码行号(字节码偏移量)之间的对应关系。它并不是运行时必须的属性,但默认会生成到Class文件之中,可以在Javac中使用-g:none或-g:lines选项来取消或要求生成这项信息。如果选择不生成LineNumberTable属性表,对程序运行产生的最主要的影响就是在抛出异常时,堆栈中将不会显示出错的行号,并且在调试程序的时候无法按照源码来设置断点。

LineNumberTable属性表结构如下表,

根据LineNumberTable属性结构,如上图,attribute_name_index = 0x0008 = #8 查看常量池#8 =“LineNumberTable” ,接着便是 attribute_length=0x00000006 = 6,

接下来2位为0x0001,即该line_number_table中只有一个line_number_info表,字节码行号start_pc为0x0000,l源码行号ine_number为0x0002,LineNumberTable属性结束。

 

转载于:https://www.cnblogs.com/shyroke/p/9062058.html

你可能感兴趣的文章
区分SQL Server关联查询之inner join,left join, right join, full outer join并图解
查看>>
mysql日志详细解析
查看>>
HttpClientUtil
查看>>
SQL 语句转换格式函数Cast、Convert
查看>>
Caused by: java.lang.ClassNotFoundException: com/sun/tools/internal/xjc/api/XJC
查看>>
深度|余凯:基于深度学习的自动驾驶之路
查看>>
十几个remote control software
查看>>
重量级框架
查看>>
导入Mybatis_Spring项目遇到的问题
查看>>
ERP入门
查看>>
【转】@Override must override a superclass method 问题解决
查看>>
统一认证系统(三)
查看>>
CentOS6.5安装完没有网络的解决办法
查看>>
利用Nodejs & Cheerio & Request抓取Lofter美女图片
查看>>
django 部署到 apache
查看>>
crontab命令
查看>>
为什么要使用云盘?
查看>>
spring依赖注入单元测试:expected single matching bean but found 2
查看>>
C++ 用libcurl库进行http通讯网络编程(转)
查看>>
锁表 for update
查看>>