Class文件结构介绍[属性表集合],被面试官问的Java问题难倒了

在这里插入图片描述

| 名称 | 类型 | 属性 |

| :-- | :-- | :-- |

| u2 | attribute_name_index | 1 |

| u4 | attribute_length | 1 |

| u1 | info | attribute_length |

attribute_info又可细分为以下21种(即《Java虚拟机规范(Java SE 7)》中预定义了的21项虚拟机实现应当能识别的属性):

| 属性名称 | 使用位置 | 含义 |

| :-- | :-- | :-- |

| Code | 方法表中 | Java代码编译成的字节码指令(即:具体的方法逻辑字节码指令) |

| ConstantValue | 字段表中 | final关键字定义的常量值 |

| Deprecated | 类中、方法表中、字段表中 | 被声明为deprecated的方法和字段 |

| Exceptions | 方法表中 | 方法声明的异常 |

| LocalVariableTable | Code属性中 | 方法的局部变量描述 |

| LocalVariableTypeTable | 类中 | JDK1.5中新增的属性,它使用特征签名代替描述符,是为了引入泛型语法之后能描述泛型参数化类型而添加 |

| InnerClasses | 类中 | 内部类列表 |

| EnclosingMethod | 类中 | 仅当一个类为局部类或者匿名类时,才能拥有这个属性,这个属性用于表示这个类所在的外围方法 |

| LineNumberTable | Code属性中 | Java源码的行号与字节码指令的对应关系 |

| StackMapTable | Code属性中 | JDK1.6中新增的属性,供新的类型检查验证器(Type Checker)检查和处理目标方法的局部变量和操作数栈所需要的类型是否匹配 |

| Signature | 类中、方法表中、字段表中 | JDK1.5新增的属性,这个属性用于支持泛型情况下的方法签名,在Java语言中,任何类、接口、初始化方法或成员的泛型签名如果包含了类型变量(Type Variables)或参数类型(Parameterized Types),则Signature属性会为它记录泛型签名信息。由于Java的泛型采用擦除法实现,在为了避免类型信息被擦除后导致签名混乱,需要这个属性记录泛型中的相关信息 |

| SourceFile | 类中 | 记录源文件名称 |

| SourceDebugExtension | 类中 | JDK1.6中新增的属性,SourceDebugExtension用于存储额外的调试信息。如在进行JSP文件调试时,无法通过Java堆栈来定位到JSP文件的行号,JSR-45规范为这些非Java语言编写,却需要编译成字节码运行在Java虚拟机汇中的程序提供了一个进行调试的标准机制,使用SourceDebugExtension就可以存储这些调试信息。 |

| Synthetic | 类中、方法表中、字段表中 | 标识方法或字段为编译器自动产生的 |

| RuntimeVisibleAnnotations | 类中、方法表中、字段表中 | JDK1.5中新增的属性,为动态注解提供支持。RuntimeVisibleAnnotations属性,用于指明哪些注解是运行时(实际上运行时就是进行反射调用)可见的。 |

| RuntimeInvisibleAnnotations | 类中、方法表中、字段表中 | JDK1.5中新增的属性,作用与RuntimeVisibleAnnotations相反用于指明哪些注解是运行时不可见的。 |

| RuntimeVisible

ParameterAnnotations | 方法表中 | JDK1.5中新增的属性,作用与RuntimeVisibleAnnotations类似,只不过作用对象为方法的参数。 |

| RuntimeInvisible

ParameterAnnotations | 方法表中 | JDK1.5中新增的属性,作用与RuntimeInvisibleAnnotations类似,只不过作用对象为方法的参数。 |

| AnnotationDefault | 方法表中 | JDK1.5中新增的属性,用于记录注解类元素的默认值 |

| BootstrapMethods | 类中 | JDK1.7新增的属性,用于保存invokedynamic指令引用的引导方法限定符 |

Code属性


java程序方法体重的代码经过Javac编译器处理后,最终变为字节码指令存储在Code属性内,Code属性出现在方法表的属性集合中(如下图),但并非所有的方法都必须存在这个属性,譬如接口或者抽象类中的方法就不存在Code属性,如果方法表有Code属性存在。

在这里插入图片描述

Code属性的结构图:

在这里插入图片描述

| 名称 | 类型 | 数量 |

| :-- | :-- | :-- |

| attribute_name_index | u2 | 1 |

| attribute_length | u4 | 1 |

| max_stack | u2 | 1 |

| max_locals | u2 | 1 |

| code_length | u4 | 1 |

| code | u1 | code_length |

| exception_table_length | u2 | 1 |

| exception_table | exception_info | exception_table_length |

| attribute_count | u2 | 1 |

| attributes | attribute_info | attribute_count |

attribute_name_index

指向CONSTANT_Utf8_info型常量的索引,常量值固定为“Code”,它代表了属性的名称。

在这里插入图片描述

在这里插入图片描述

attribute_length:指示了属性值的长度。由于attribute_name_index与attribute_length一共占6个字节,所以属性值的长度又等于属性表总长度-6。

max_stack:操作数栈(Operand Stacks)允许深度的最大值。在方法执行的任意时刻,操作数栈都不会超过这个深度. 虚拟机的时候需要根据这个值来分配栈帧(Stack Frame)中的操作占深度。

max_locals:代表了局部变量表所需的存储空间。在这里,max_locals的单位是Slot槽。Slot是虚拟机为局部变量分配内存所使用的最小单位。一个Slot的空间大小为四字节,对于byte、char、float、int、 short、 boolean、和returnAddress等长度不超过32位的数据类型,每个局部变量占用一个Slot;而double和long这种64位的数据则需要两个连续的Slot来存储。

:并不是在方法中用到了多少局部变量,就把这些局部变量所占用放入Slot个数之和作为,max_locals的值,原因是局部变量表中的Slot槽可以重用。当代码执行超出一个局部变量的做用户与使时,这个局部变量所占用放入Slot可以被其它局部变量所使用,Javac编译器会根据变量的作用域来分配Slot给各个变量使用,然后计算出max_locals的大小。

code_length、code:用来存储Java源码编译后的字节码指令。code_length代表字节码长度;code是用于存储Java字节码指令的一系列字节流。

public void fun1(){

int b = 20;

int c = 30;

int d = b+c+age;

System.out.println(d);

}

对照虚拟机字节码指令表 我们来看下Code中的指令

在这里插入图片描述

| 指令 | 字节码 | 说明 |

| :-- | :-- | :-- |

| 10 14 | bipush 20 | 将20推送至栈顶 |

| 3C | istore_1 | 将栈顶20存入第二个本地变量(b) |

| 10 1E | bipush 30 | 将30推送至栈顶 |

| 3D | istore_2 | 将栈顶30型数值存入第三个本地变量( c ) |

| 1B | iload_1 | 将第二个int型本地变量推送至栈顶(b) |

| 1C | iload_2 | 将第三个int型本地变量推送至栈顶( c ) |

| 60 | iadd | 将栈顶两int型数值相加并将结果压入栈顶(b+c=50) |

| 2A | aload_0 | 将第一个引用类型本地变量推送至栈顶(age) |

| B4 00 13 | getfield #19 | 获取指定类的实例域, 并将其压入栈顶age |

| 60 | iadd | 将栈顶两int型数值相加并将结果压入栈顶(age+50=68) |

| 3E | istore_3 | 将第四个int型本地变量推送至栈顶(68) |

| B2 00 1A | getstatic #26 | 获取指定类的静态域, 并将其压入栈顶

java/lang/System.out |

| 1D | iload_3 | 将第四个int型本地变量推送至栈顶(68) |

| B6 00 20 | invokevirtual #32 | 调用实例方法(调用println方法) |

| B1 | return | 从当前方法返回void |

javap输出:

在这里插入图片描述

Exceptions属性


Exception属性的作用是列举出方法的声明异常。

| 名称 | 类型 | 数量 |

| :-- | :-- | :-- |

| attribute_name_index | u2 | 1 |

小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数初中级Java工程师,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年最新Java开发全套学习资料》送给大家,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
img
img
img

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频

如果你觉得这些内容对你有帮助,可以添加下面V无偿领取!(备注Java)
img

总结

三个工作日收到了offer,头条面试体验还是很棒的,这次的头条面试好像每面技术都问了我算法,然后就是中间件、MySQL、Redis、Kafka、网络等等。

  • 第一个是算法

关于算法,我觉得最好的是刷题,作死的刷的,多做多练习,加上自己的理解,还是比较容易拿下的。

而且,我貌似是将《算法刷题LeetCode中文版》、《算法的乐趣》大概都过了一遍,尤其是这本

《算法刷题LeetCode中文版》总共有15个章节:编程技巧、线性表、字符串、栈和队列、树、排序、查找、暴力枚举法、广度优先搜索、深度优先搜索、分治法、贪心法、动态规划、图、细节实现题

最新出炉,头条三面技术四面HR,看我如何一步一步攻克面试官?

《算法的乐趣》共有23个章节:

最新出炉,头条三面技术四面HR,看我如何一步一步攻克面试官?

最新出炉,头条三面技术四面HR,看我如何一步一步攻克面试官?

  • 第二个是Redis、MySQL、kafka(给大家看下我都有哪些复习笔记)

基本上都是面试真题解析、笔记和学习大纲图,感觉复习也就需要这些吧(个人意见)

最新出炉,头条三面技术四面HR,看我如何一步一步攻克面试官?

  • 第三个是网络(给大家看一本我之前得到的《JAVA核心知识整理》包括30个章节分类,这本283页的JAVA核心知识整理还是很不错的,一次性总结了30个分享的大知识点)

最新出炉,头条三面技术四面HR,看我如何一步一步攻克面试官?

  • 第二个是Redis、MySQL、kafka(给大家看下我都有哪些复习笔记)

基本上都是面试真题解析、笔记和学习大纲图,感觉复习也就需要这些吧(个人意见)

[外链图片转存中…(img-aTjuML0J-1711044704744)]

  • 第三个是网络(给大家看一本我之前得到的《JAVA核心知识整理》包括30个章节分类,这本283页的JAVA核心知识整理还是很不错的,一次性总结了30个分享的大知识点)

[外链图片转存中…(img-mHltWEaY-1711044704744)]

本文已被CODING开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码】收录

  • 25
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值