我的编程空间,编程开发者的网络收藏夹
学习永远不晚

Java class文件格式之属性详解_动力节点java学院整理

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

Java class文件格式之属性详解_动力节点java学院整理

Code属性

code属性是方法的一个最重要的属性。 因为它里面存放的是方法的字节码指令, 除此之外还存放了和操作数栈,局部变量相关的信息。 所有不是抽象的方法, 都必须在method_info中的attributes中有一个Code属性。下面是Code属性的结构, 为了更直观的展示Code属性和method_info的包含关系, 特意画出了method_info:

Java class文件格式之属性详解_动力节点java学院整理

下面依次介绍code属性中的各个部分。

attribute_name_index指向常量池中的一个CONSTANT_Utf8_info , 这个CONSTANT_Utf8_info 中存放的是当前属性的名字 “Code” 。

attribute_length给出了当前Code属性的长度(不包括前六字节)。

max_stack 指定当前方法被执行引擎执行的时候, 在栈帧中需要分配的操作数栈的大小。

max_locals指定当前方法被执行引擎执行的时候, 在栈帧中需要分配的局部表量表的大小。注意, 这个数字并不是局部变量的个数, 因为根据局部变量的作用域不同, 在执行到一个局部变量以外时, 下一个局部变量可以重用上一个局部变量的空间(每个局部变量在局部变量表中占用一个或两个Slot)。 方法中的局部变量包括方法的参数, 方法的默认参数this, 方法体中定义的变量, catch语句中的异常对象。 关于执行引擎的相关内容会在后面的博客中讲到。

code_length指定该方法的字节码的长度, class文件中每条字节码占一个字节。

code存放字节码指令本身, 它的长度是code_length个字节。

exception_table_length 指定异常表的大小

exception_table就是所谓的异常表, 它是对方法体中try-catch_finally的描述。 exception_table可以看做是一个数组, 每个数组项是一个exception_info结构, 一般来说每个catch块对应一个exception_info,编译器也可能会为当前方法生成一些exception_info。 exception_info的结构如下(为了直观的显示exception_info, exception_table和Code属性的关系, 画出了Code属性,的话读者就会更清楚各个数据项之间的位置关系和包含关系):

Java class文件格式之属性详解_动力节点java学院整理

下面讲解exception_info中的各个字段的意思。

start_pc是从字节码(Code属性中的code部分)起始处到当前异常处理器起始处的偏移量。

end_pc是从字节码起始处到当前异常处理器末尾的偏移量。

handler_pc是指当前异常处理器用来处理异常(即catch块)的第一条指令相对于字节码开始处的偏移量。

catch_type是一个常量池索引, 指向常量池中的一个CONSTANT_Class_info数据项, 该数据项描述了catch块中的异常的类型信息。这个类型必须是java.lang.Throwable的或其子类。

所以可以总结, 一个异常处理器(exception_info)的意思是: 如果偏移量从start_pc到end_pc之间的字节码出现了catch_type描述的类型的异常, 那么就跳转到偏移量为handler_pc的字节码处去执行。如果catch_type为0, 就代表不引用任何常量池项(再回顾一下, 常量池中的项是从1开始计的), 那么这个exception_info用于实现finally子句。

我们一直在介绍Code属性, 只不过刚才进行了一个小插曲, 介绍了Code属性中的exception_table中的exception_info的详细信息。 下面我们继续介绍Code 属性中的其他信息, 希望读者不要被绕晕了 : )

attributes_count 表示当前Code 属性中存在的其他属性的个数。 现在我们知道, class中的属性, 不仅会出现在顶层的class中, 会存在field_info中, 会存在method_info中, 甚至还会出现在属性中。 

attributes可以看做是一个数组, 里面存放了Code属性中的其他属性。 Code 属性中可以出现的其他属性有LineNumberTable和LocalVariableTable 。 这两个属性会在下面介绍。

LineNumberTable属性

LineNumberTable属性存在于Code属性中, 它建立了字节码偏移量到源代码行号之间的联系。 这个属性是可选的, 编译器可以选择不生成该属性。下面是该属性的结构(同样给出了全局的位置关系,LineNumberTable在图的右下角部分):

Java class文件格式之属性详解_动力节点java学院整理

由于这个属性并不是重点, 我们在此简单的讲述。 

每个LineNumberTable中的line_number_table部分, 可以看做是一个数组, 数组的每项是一个line_number_info , 每个line_number_info 结构描述了一条字节码和源码行号的对应关系。 其中start_pc是这个line_number_info 描述的字节码指令的偏移量, line_number是这个line_number_info 描述的字节码指令对应的源码中的行号。可以看出, 方法中的每条字节码都对应一个line_number_info , 这些line_number_info 中的line_number可以指向相同的行号, 因为一行源码可以编译出多条字节码。

LocalVariableTable属性 

LocalVariableTable 属性建立了方法中的局部变量与源代码中的局部变量之间的对应关系。 这个属性存在于Code属性中。 这个属性是可选的, 编译器可以选择不生成这个属性。该属性的结构如下:(同样给出了全局的位置关系图,LocalVariableTable 在该图的右下角 )

Java class文件格式之属性详解_动力节点java学院整理

由于这个属性相对不那么重要, 这里只是大概讲解一下。

每个LocalVariableTable 的local_variable_table部分可以看做是一个数组, 每个数组项是一个叫做local_variable_info的结构, 该结构描述了某个局部变量的变量名和描述符, 还有和源代码的对应关系。下面讲解local_variable_info的各个部分:

start_pc是当前local_variable_info所对应的局部变量的作用域的起始字节码偏移量;

length是当前local_variable_info所对应的局部变量的作用域的大小。 也就是从字节码偏移量start_pc 到start_pc+length就是当前局部变量的作用域范围;

name_index指向常量池中的一个CONSTANT_Utf8_info, 该CONSTANT_Utf8_info描述了当前局部变量的变量名;

descriptor_index指向常量池中的一个CONSTANT_Utf8_info, 该CONSTANT_Utf8_info描述了当前局部变量的描述符;

index描述了在该方法被执行时,当前局部变量在栈帧中局部变量表中的位置。 

由此可知, 方法中的每个局部变量都会对应一个local_variable_info 。 

Exceptions属性

首先需要说明, Exceptions属性不是存在于Code属性中的, 它存在于method_info中的attributes中。 和Code属性是平级的。 这个属性描述的是方法声明的可能会抛出的异常, 也就是方法定义后面的throws声明的异常列表, 请不要和上面提到的异常处理器混淆。 异常处理器描述了方法的字节码如何处理异常, 而Exceptions属性描述方法可能会抛出哪些以异常。下面讲解Exceptions属性的结构(左下角为Exceptions属性):

Java class文件格式之属性详解_动力节点java学院整理

下面讲解Exceptions属性中的信息。 

attribute_name_index和attribute_length就不多说了, 和其他属性是一样的。 

number_of_exceptions是该方法要抛出的异常的个数。 

exceptions_index_table可以看做一个数组, 这个数组中的每一项占两个字节, 这两个字节是对常量池的索引, 它指向一个常量池中的CONSTANT_Class_info。 这个CONSTANT_Class_info描述了一个被抛出的异常的类型。 

总结

到此为止, 和方法相关的属性就介绍完了。 这篇博客讲解的内容相对比较复杂。 下面以一个实例进行验证, 实例代码:

package com.bjpowernode.test; public class Test {   public void test() throws Exception{     int localVar = 0;     try{       Class.forName("com.bjpowernode.test.Person");     }catch(ClassNotFoundException e){       throw e;     }finally{       System.out.println(localVar);     }   } }

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

Java class文件格式之属性详解_动力节点java学院整理

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

Java class文件格式之属性详解_动力节点java学院整理

Code属性code属性是方法的一个最重要的属性。 因为它里面存放的是方法的字节码指令, 除此之外还存放了和操作数栈,局部变量相关的信息。 所有不是抽象的方法, 都必须在method_info中的attributes中有一个Code属性。下
2023-05-31

Java class文件格式之常量池_动力节点Java学院整理

常量池中各数据项类型详解常量池中的数据项是通过索引来引用的, 常量池中的各个数据项之间也会相互引用。在这11中常量池数据项类型中, 有两种比较基础, 之所以说它们基础, 是因为这两种类型的数据项会被其他类型的数据项引用。 这两种数据类型就是
2023-05-31

Java class文件格式总结_动力节点Java学院整理

我们都知道JVM能够识别的只有class格式的文件, 而源文件只是我们人能识别的, 不能被JVM识别。 那我们要在更深的层次上理解Java语言, 理解JVM, 只懂源文件是不够的, 因为虚拟机的很多的行为, 是在class文件中定义的, 而
2023-05-31

深入理解Java class文件格式_动力节点Java学院整理

Class文件在Java体系结构中的位置和作用对于理解JVM和深入理解Java语言, 学习并了解class文件的格式都是必须要掌握的功课。 原因很简单, JVM不会理解我们写的Java源文件, 我们必须把Java源文件编译成class文件,
2023-05-31

Java class文件格式之数据类型(二)_动力节点Java学院整理

常量池中各数据项类型详解(续)(8) CONSTANT_Class_info常量池中的一个CONSTANT_Class_info, 可以看做是CONSTANT_Class数据类型的一个实例。 他是对类或者接口的符号引用。 它描述的可以是当前
2023-05-31

Java class文件格式之特殊字符串_动力节点Java学院整理

class文件中的特殊字符串首先说明一下, 所谓的特殊字符串出现在class文件中的常量池中,本着循序渐进和减少跨度的原则, 首先把class文件中的特殊字符串做一个详细的介绍, 然后再回过头来继续讲解常量池。 现在我们将重点放在特殊字符串
2023-05-31

Java新特性之Nashorn_动力节点Java学院整理

Nashorn是什么Nashorn,发音“nass-horn”,是德国二战时一个坦克的命名,同时也是java8新一代的javascript引擎--替代老旧,缓慢的Rhino,符合 ECMAScript-262 5.1 版语言规范。你可能想j
2023-05-31

Java8新特性之Base64详解_动力节点Java学院整理

BASE64 编码是一种常用的字符编码,在很多地方都会用到。但base64不是安全领域下的加密解密算法。能起到安全作用的效果很差,而且很容易破解,他核心作用应该是传输数据的正确性,有些网关或系统只能使用ASCII字符。Base64就是用来将
2023-05-31

Java Scaner类详解_动力节点Java学院整理

Java.util.Scanner是Java5.0的新特征,主要功能是简化文本扫描。这个类最实用的地方表现在获取控制台输入,其他的功能都很鸡肋,尽管Java API文档中列举了大量的API方法,但是都不怎么地。 一、扫描控制台输入 这个例子
2023-05-31

Java System类详解_动力节点Java学院整理

System类是jdk提供的一个工具类,有final修饰,不可继承,由名字可以看出来,其中的操作多数和系统相关。其功能主要如下: 标准输入输出,如out、in、err 外部定义的属性和环境变量的访问,如getenv()/setenv()和g
2023-05-31

Java Runtime类详解_动力节点Java学院整理

一、概述 Runtime类封装了运行时的环境。每个 Java 应用程序都有一个 Runtime 类实例,使应用程序能够与其运行的环境相连接。一般不能实例化一个Runtime对象,应用程序也不能创建自己的 Runtime 类实例,但
2023-05-31

Java8新特性之StampedLock_动力节点Java学院整理

Java8就像一个宝藏,一个小的API改进,也足与写一篇文章,比如同步,一直是多线程并发编程的一个老话题,相信没有人喜欢同步的代码,这会降低应用的吞吐量等性能指标,最坏的时候会挂起死机,但是即使这样你也没得选择,因为要保证信息的正确性。所以
2023-05-31

Java设计模式之代理模式_动力节点Java学院整理

引言Java 动态代理机制的出现,使得 Java 开发人员不用手工编写代理类,只要简单地指定一组接口及委托类对象,便能动态地获得代理类。代理类会负责将所有的方法调用分派到委托对象上反射执行,在分派执行的过程中,开发人员还可以按需调整委托类对
2023-05-31

Java反射机制详解_动力节点Java学院整理

Java 反射机制介绍Java 反射机制。通俗来讲呢,就是在运行状态中,我们可以根据“类的部分已经的信息”来还原“类的全部的信息”。这里“类的部分已经的信息”,可以是“类名”或“类的对象”等信息。“类的全部信息”就是指“类的属性,方法,继承
2023-05-31

Java8新特性之精简的JRE详解_动力节点Java学院整理

Oracle公司如期发布了Java 8正式版!没有让广大javaer失望。对于一个人来说,18岁是人生的转折点,从稚嫩走向成熟,法律意味着你是完全民事行为能力人,不再收益于未成年人保护法,到今年为止,java也走过了18年,java8是一个
2023-05-31

Java设计模式之策略模式_动力节点Java学院整理

定义:定义一组算法,将每个算法都封装起来,并且使他们之间可以互换。类型:行为类模式类图: 策略模式是对算法的封装,把一系列的算法分别封装到对应的类中,并且这些类实现相同的接口,相互之间可以替换。在前面说过的行为类模式中,有一种模
2023-05-31

Java中的clone方法详解_动力节点Java学院整理

Java中对象的创建clone顾名思义就是复制, 在Java语言中, clone方法被对象调用,所以会复制对象。所谓的复制对象,首先要分配一个和源对象同样大小的空间,在这个空间中创建一个新的对象。那么在java语言中,有几种方式可以创建对象
2023-05-31

Java8新特性之再见Permgen_动力节点Java学院整理

很多开发者都在其系统中见过“java.lang.OutOfMemoryError: PermGen space”这一问题。这往往是由类加载器相关的内存泄漏以及新类加载器的创建导致的,通常出现于代码热部署时。相对于正式产品,该问题在开发机上出
2023-05-31

Java设计模式之迭代器模式_动力节点Java学院整理

定义:提供一种方法访问一个容器对象中各个元素,而又不暴露该对象的内部细节。类型:行为类模式类图: 如果要问Java中使用最多的一种模式,答案不是单例模式,也不是工厂模式,更不是策略模式,而是迭代器模式,先来看一段代码吧:publ
2023-05-31

详解Redis命令和键_动力节点Java学院整理

Redis命令用于在redis服务器上执行某些操作。 要在Redis服务器上运行的命令,需要一个Redis客户端。 Redis客户端在Redis的包,这已经我们前面安装使用过了。语法Redis客户端的基本语法如下:$redis-cli例子下
2022-06-04

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录