属性表

预备知识

  • javac -g Xxx.java 在生成class文件的时候生成所有调试信息
  • javap -v Xxx.class 输出附加信息

属性表结构

类型 名称 数量 备注
u2 attribute_name_index 1 属性名称索引,指向一个CONSTANT_Utf8_info型常量的索引
u4 attribute_length 1 该属性表的长度
u1 info attribute_length 属性值

Code属性表

Code属性表结构释义

  • attribute_name_index是一项指向CONSTANT_Utf8_info型常量的索引,对应的值固定为‘Code’,代表了该属性的属性名称。

  • attribute_length代表了属性值的长度。属性值的长度=属性表总长度-6个字节。

  • max_stack代表操作数栈深度的最大值。虚拟机运行时根据该值来分配栈帧中操作数栈的深度。

  • max_locals 代表了局部变量表所需的存储空间。其计算单位为‘变量槽’。变量槽是JVM为局部变量表分配内存所使用的最小单位。对于byte、char、float、int、short、boolean及returnAddress等长度不超过32位的数据类型,每个局部变量占用1个变量槽,double及long这两种64位的数据类型,占用两个变量槽。

    • 局部变量表中的变量槽会被复用,所以变量槽的个数不一定等于参数个数。当代码执行 超过一个变量的作用域时,其原型占用的变量槽将会被复用。
    • 操作数栈及局部变量表直接决定了该方法的栈帧所耗费的内存。
  • code_length代表Java源程序编译后生成的字节码指令个数,由于一个字节码占用1字节,所以也就是字节码的长度。

    • 理论值为2^32,实际最大值为65535。
  • code 用于存储编译生产的一些列字节码指令。

  • exception_info 该方法的显示异常处理表集合,非必须。

    • 显示异常处理表结构

      类型 名称 数量
      u2 start_pc 1
      u2 end_pc 1
      u2 handler_pc 1
      u2 catch_type 1

      上表表示当字节码从[start_pc,end_pc)行出现了类型为catch_type或其子类的异常,那么就转至handler_pc行进行处理。当catch_type为0时,代表任意异常都需要跳转到handler_pc行处理。

      -注意 : 此处的行指的是字节码相对于方法体开始的偏移量。

Code属性表实例

public class Test{private static final int size = 100;public void sout(){System.out.println(size);}public int toDouble(int prame){return 2*prame;}public int add(int p1,int p2){return p1+p2;}public static int toTriple(int prame){return 3*prame;}
}

将代码编译 javac -g Test.java,在反编译javap -v Test.class

Classfile /D:/notes/JVM/code/Test.classLast modified 2021-3-29; size 746 bytesMD5 checksum a1a23cf998350d444d9438782f3af659Compiled from "Test.java"
public class Testminor version: 0major version: 52flags: ACC_PUBLIC, ACC_SUPER
Constant pool:#1 = Methodref          #5.#28         // java/lang/Object."<init>":()V#2 = Fieldref           #29.#30        // java/lang/System.out:Ljava/io/PrintStream;#3 = Class              #31            // Test#4 = Methodref          #32.#33        // java/io/PrintStream.println:(I)V#5 = Class              #34            // java/lang/Object#6 = Utf8               size#7 = Utf8               I#8 = Utf8               ConstantValue#9 = Integer            100#10 = Utf8               <init>#11 = Utf8               ()V#12 = Utf8               Code#13 = Utf8               LineNumberTable#14 = Utf8               LocalVariableTable#15 = Utf8               this#16 = Utf8               LTest;#17 = Utf8               sout#18 = Utf8               toDouble#19 = Utf8               (I)I#20 = Utf8               prame#21 = Utf8               add#22 = Utf8               (II)I#23 = Utf8               p1#24 = Utf8               p2#25 = Utf8               toTriple#26 = Utf8               SourceFile#27 = Utf8               Test.java#28 = NameAndType        #10:#11        // "<init>":()V#29 = Class              #35            // java/lang/System#30 = NameAndType        #36:#37        // out:Ljava/io/PrintStream;#31 = Utf8               Test#32 = Class              #38            // java/io/PrintStream#33 = NameAndType        #39:#40        // println:(I)V#34 = Utf8               java/lang/Object#35 = Utf8               java/lang/System#36 = Utf8               out#37 = Utf8               Ljava/io/PrintStream;#38 = Utf8               java/io/PrintStream#39 = Utf8               println#40 = Utf8               (I)V
{public Test();descriptor: ()Vflags: ACC_PUBLICCode:stack=1, locals=1, args_size=10: aload_01: invokespecial #1                  // Method java/lang/Object."<init>":()V4: returnLineNumberTable:line 1: 0LocalVariableTable:Start  Length  Slot  Name   Signature0       5     0  this   LTest;    // 疑问:为什么这里的Length为5?public void sout();descriptor: ()Vflags: ACC_PUBLICCode:stack=2, locals=1, args_size=10: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;3: bipush        1005: invokevirtual #4                  // Method java/io/PrintStream.println:(I)V8: returnLineNumberTable:line 5: 0line 6: 8LocalVariableTable:Start  Length  Slot  Name   Signature0       9     0  this   LTest;public int toDouble(int);descriptor: (I)Iflags: ACC_PUBLICCode:stack=2, locals=2, args_size=20: iconst_21: iload_12: imul3: ireturnLineNumberTable:line 9: 0LocalVariableTable:Start  Length  Slot  Name   Signature0       4     0  this   LTest;0       4     1 prame   Ipublic int add(int, int);descriptor: (II)Iflags: ACC_PUBLICCode:stack=2, locals=3, args_size=30: iload_11: iload_22: iadd3: ireturnLineNumberTable:line 13: 0LocalVariableTable:Start  Length  Slot  Name   Signature0       4     0  this   LTest;0       4     1    p1   I0       4     2    p2   Ipublic static int toTriple(int);descriptor: (I)Iflags: ACC_PUBLIC, ACC_STATICCode:stack=2, locals=1, args_size=10: iconst_31: iload_02: imul3: ireturnLineNumberTable:line 17: 0LocalVariableTable:Start  Length  Slot  Name   Signature0       4     0 prame   I
}

现在对toDouble方法进行分析

Code属性下

  • stack=2表示操作数栈的最大深度为2
  • locals=2表示本地变量表的存储空间为2个变量槽
  • args_size=2表示方法的传参有2个
    • 这里有个问题,明明方法签名为toDouble(int prame),只有一个参数,为什么这里显示有两个参数呢?因为在编译的时候,会自动的传入一个参数this。并放到局部变量表的0号槽中。
  • LocalVariableTable 表示各变量在局部变量表中的存储情况。
Code:stack=2, locals=2, args_size=20: iconst_2 # 将int型数值2推送到操作数栈顶1: iload_1  # 将第二个int型本地变量推动至栈顶,即将局部变量表中solt索引为1的变量推送至操作数栈栈顶2: imul    # 将栈顶两个int类型数值相乘并将结果压入栈顶3: ireturn  # 从方法中返回int类型的数据,即将操作数栈栈顶元素弹出

Exceptions属性

Exceptions属性是在方法表中与Code属性平级的一项属性,与Code属性中的异常表不是同一东西,列举出方法中可能抛出的受查异常(Checked Excepitons) , 也就是方法描述时在throws关键字后面列举的异常。

Exceptions属性结构

类型 名称 数量 备注
u2 attribute_name_index 1 属性名索引
u4 attribute_length 1 属性长度
u2 number_of_exceptions 1 抛出的受查异常种数
u2 exception_index_table nubmer_of_exceptions 指向常量池中CONSTANT_class_info型常量的索引

LineNumberTable属性

用来描述Java源码与字节码行号之间的对应关系。这里的字节码行号指的是字节码距方法体开始的偏移量。是一个非必须属性。默认生成。可使用-g: none-g:lines来选择或者取消。

若不生成改属性,那么在抛出异常的时候,堆栈中将不会显示出错的行号,在调试时无法按照源码行来设置断点。

LineNumberTable属性结构

类型 名称 数量 备注
u2 attribute_name_index 1 属性名索引
u4 attribute_length 1 属性长度
u2 line_number_table_length 1 属性个数
line_number_info line_number_table line_number_table_length line_number_info集合

line_number_info

类型 名称 备注
u2 start_pc 字节码行号
u2 line_number Java源码行号

LocalVariableTable

用来描述栈帧中局部变量表的变量与Java源码中定义的变量之间的关系,是非必须的。-g:none,-g: vars来取消或选择。默认会生成到class文件中,若取消该属性,那么当他人引用时,所有的参数名称都会消失。

LocalVariableTable属性结构

类型 名称 数量 备注
u2 attribute_name_index 1 属性名索引
u4 attribute_length 1 属性长度
u2 local_variable_table_length 1 本地变量表长度
local_variable_info local_variable_table local_variable_table_length 本地变量表

local_variable_info结构

类型 名称 数量 备注
u2 start_pc 1 该局部变量的声明周期的开始字节码偏移量
u2 length 1 该局部变量的作用范围
u2 name_index 1 是指向CONSTANT_Utf8_info型常量的索引,代表局部变量的名称
u2 descriptor_index 1 是指向CONSTANT_Utf8_info型常量的索引,代表局部变量的描述符
u2 index 1 在局部变量表中的变量槽位置

在JDK引入泛型后增加了**LocalVariableTypeTable **属性,仅仅是将descriptor_index替换为字段的特征签名(Signature) 。

SourceFile及SourceDebugExtension属性

SourceFile属性用于记录生成这个Class文件的源码文件名称。 可选;-g:none,-g: source来关闭或开启。若不生成,在抛出异常的时候,堆栈中不会显示出错代码所属的文件名。

SouceFile属性结构

类型 名称 数量 备注
u2 attribute_name_index 1 属性名索引
u4 attribute_length 1 属性长度
u2 sourcefile_index 1 指向常量池中CONSTANT_Utf8_info型常量的索引, 常量值是源码文件的文件名

JDK 5时, 新增了SourceDebugExtension属性用于存储额外的代码调试信息。

类型 名称 数量 备注
u2 attribute_name_index 1 属性名索引
u4 attribute_length 1 属性长度
u1 debug_extension[attribute_length] 1 额外的调试信息

ConstantValue属性

该属性的作用是通知虚拟机自动为静态变量赋值。只有被static修饰的变量才能使用这项属性。

非静态变量 实例构造器()方法中赋值
静态变量 类构造器()方法中赋值
静态变量 使用ConstantValue属性

Oracle公司的选择是,常量(static final共同修饰的变量)且其类型为基础类型或String,使用ConstantValue属性来进行初始化,非基础类型及字符串,或仅被static修饰那么在()中进行初始化。

ConstantValue属性结构

类型 名称 数量 备注
u2 attribute_name_index 1 属性名索引
u4 attribute_length 1 属性长度
u2 constantvalue_index 1 常量池中一个字面量的引用

JVM003_属性表相关推荐

  1. 将FeatClass属性表高效率转换成DataTable

    把IFeatureClass\ ITable转换成DataTable,效率高. 方法一 ITable遍历行 1.用IFeatureClass属性查询的方式较慢,这样速度可提高几十倍. 2.避免了hre ...

  2. VS创建props属性表并在新项目中导入props属性表

    创建props属性表过程见配置PCL的一个例子:VS2019配置PCL 上面一篇执行完现在生成了pclX64.props 创建一个新的项目: 创建好了之后,复制进来两个文件,那个pcd模板文件见上面那 ...

  3. 去除ArcMap连接空间数据库中多余的属性表

    这个操作目前可能不具有可行性,但是为了完整性还是在下面讲一下吧.如有兴趣的小伙伴,可以按照下面的操作方式去尝试. 一.需求 去除ArcMap连接空间数据库中多余的属性表. PL/SQL中查询得到的内容 ...

  4. vs如何将工程配置,保存到属性表

    本机有个: opencv412_release_x64_vs2017.props 现在介绍一种将工程配置,保存到属性表的方法,那么下次新建工程时,只要添加这个属性表,整个配置就完成了-- 首先新建一个 ...

  5. gis属性表怎么导成excel_使用Python脚本将Excel表批量赋值到ArcGIS属性表

    现需要将Excel表信息批量赋值(不是挂接)到Shp文件的属性表,两张表的字段.记录数一模一样,至于为什么会出现这样的问题,咱也不敢问,只有想个法子把它搞定! 原始的Excel信息表共57列,总共3万 ...

  6. 【Java 虚拟机原理】Class 字节码二进制文件分析 五 ( 方法计数器 | 方法表 | 访问标志 | 方法名称索引 | 方法返回值类型 | 方法属性数量 | 方法属性表 )

    文章目录 前言 一.方法表结构 二.方法计数器 三.方法表数据解析 ( init 构造方法 ) 1.方法访问标志 2.方法名称索引 3.方法返回类型 4.方法属性数量 前言 上一篇博客 [Java 虚 ...

  7. gis属性表怎么导成excel_第022篇:ArcGIS中将属性表直接导出为Excel的方法

    在使用ArcGIS处理数据的过程中,经常需要导出属性表.无论是分析也好,是添加复杂字段内容也好,Excel都要比ArcGIS本身出色得多.大家通常采用的方式是先导出成txt或dbf,再转成Excel. ...

  8. VS2010属性表的建立与灵活运用

    问题引入:在VS2010当中,进行opencv.QT等的编程时,总是需要配置很多属性还有依赖项等,为了减少每次都重复配置属性的工作量,现在可以运行属性表这个东西来简化配置.opencv也可以这样建立使 ...

  9. 超图数据集管理基本操作和添加删除属性表字段

    打开一个自带数据源:这是一个数据源模板:里面数据是空的: 右击数据集,属性: 工作空间管理器选中矢量数据集,数据集属性面板中会显示:数据集.投影.矢量.属性表.值域五个面板: 数据集信息     面板 ...

最新文章

  1. Access快速连接SQL Server的方法(VB代码为例)
  2. 让你不再害怕指针(一)
  3. 动态slimmable网络:高性能的网络轻量化方法!对比slimmable涨点5.9%
  4. activeform表单中的旧数据怎么显示_三分钟为你细数 Vue el-form 表单校验的坑点
  5. mybatis java8_mybatis如何使用Java8的日期LocalDate和LocalDateTime详解
  6. [转载]PSCAD调用MATLAB/SIMULINK之接口元件设计
  7. 前端学习(3204):类式组件
  8. Ibatis中的大于、小于、like等符号写法
  9. mssql访问 oracle
  10. C#调用GDAL算法进度信息传递
  11. Java并发面试,幸亏有点道行,不然又被忽悠了 1
  12. 请问王菲的<流年>歌词的含义
  13. 电源管理(2) - loongson cpufreq
  14. 模仿努比亚网站三(内容区域)
  15. 检测iPhone/iPod Touch/iPad设备类型 .
  16. Python数据结构之平衡二叉树
  17. 相似度算法--莱文斯坦距离加入同义词逻辑
  18. python_安卓——canv
  19. 福成股份很忙:实控人李福成被罚8万,新董事长李良则要打官司
  20. Spring基础:快速入门spring boot(7):spring boot 2.0简单介绍

热门文章

  1. Spring Boot(十三)RabbitMQ安装与集成
  2. Nginx For Windows HTTP转发和负载
  3. 第五六七章(PTA复习)
  4. 去马赛克神器 JavPlayer TG Modle 最新版
  5. EntityFramework进阶——继承
  6. git两个账号切换_Git切换账号方法
  7. dataguard mysql,[dataguard同步数据库]Dataguard环境下数据库的备份与恢复
  8. 电脑手写输入法_百度输入法“手写输入”为什么不是老年人的专利?AI的进步...
  9. java销售额查询_用JSP+JavaBean开发模式实现一个销售额的查询
  10. java dot画图_小O的图案 (Java代码)(最简单的解法)